--- --- Intro & Reviewing Linear Models

Agenda

  1. Introductions
  2. Course Admin
  3. Setup
  4. Reviewing the most important parts of Linear Models

Introductions

Hello!

My name is Josef Fruehwald, and I’m a lecturer in Linguistics and English Language.

In this first block of multivariate stats, we’ll be covering

  • The reasons why you should fit Linear Mixed Effects models.
  • How to fit LMMs.
  • How to interpret the results of LMMs.
  • How to do model comparison & parameter evaluation.
  • How to report the results of your LMMs.
  • Some pragmatic issues in thinking about your results.

In the lab sessions, you’ll work through exercises related to fitting LMMs, as well as related R programming skills related to data organization and visualization.

Course Admin

All lectures will include some R programming you can do during the lecture. I’ll recommend that you create a fresh R Notebook for each lecture.

~5 Minute Setup

First create a new R Notebook for this lecture with File > New File > R Notebook. I would recommend changing the top header metadata so it has a meaningful title:

---
title: "Multivariate - Lecture 1"
output: html_notebook
---

Delete everything else in the notebook.


Now, let’s install some packages that will be necessary in these lectures:

install.packages(
  c("tidyverse",
    "devtools",
    "lme4")
)

library("devtools")

install_github("jofrhwld/multivariate2017")

library(tidyverse)
library(lme4)
library(multivariate2017)

Workspace Hygiene

If you have a directory planning structure that you’re happy with, go ahead and do that. But I’d recommend the following directory structure & naming conventions.

├── multivariate_2017
│   └── lmm
│   │   └── assessment
│   │   └── data
│   │   └── labs

For a good philosophy on naming files, I’d recommend these slides from Jenny Bryan’s talk on Naming Things

Also good practice is to load all the packages you’re going to need at the top of your script/notebook in one block, rather than haphazardly throughout.

The Plan For This Week

Lecture

Today, we’re going to going to review the estimation & interpretation of linear models, with a focus on:

  • the scaling & transformation of predictors
  • the selection of contrasts
  • the interpreation of interaction effects

Labs

The lab exercises this week will focus on data (re)organization and vizualization.

Understanding Linear Regression

I find the best way to understand linear regressions is as recipes for drawing a graph. Let’s start off with an example relevant to my own life: the relationship between temperatures in Celcius and temperatures in Farenheit. There are two important numeric constants to convert back and forth between them:

  1. Freezing = 0°C = 32°F
  2. A change of 1°C = 1.8°F

This gives us all of the necessary components for drawing a graph of the relationship between Farenheit and Celcius. First, we know that a line plotting this relationship must cross 0 on the x-axis at 32 on the y-axis, because freezing = 0°C = 32°F.

Next, we know that for 1 every degree we move to the right, we must move up 1.8.

The line, representing this relationship, thus has the formula:

\[ y = 32 + (1.8\times x) \]

And looks like

This line has the following properties:

  1. Its Intercept, or where the line crosses 0 on the x-axis, is 32.
  2. Its Slope, is 1.8 (that is, a change of 1 on the x-axis corresponds to a change in 1.8 on the y-axis)

And, in fact, all lines, including the ones we fit using linear regression, are described in terms of their intercept (where the line crosses 0 on the x-axis) and slope.

But, let’s say you didn’t know the formula to convert back and forth between Celcius and Farenheit. Maybe you weren’t even sure that there was such a formula. And all you had were a bunch of kind of crappy thermometers that gave you both Celcius and Farenheit readings. And maybe the thermometers are kind of hard to read, or the lighting conditions are dark, or you only have limited experience in reading thermometers. In that case, the relationship between Celcius and Farenheit might look a lot more like this:

In this case, you might want to fit a linear regression. A linear regression assumes that the relationship between two variables can be captured using some line, and it tries to estimate the Intercept and Slope of this assumed line.

The way it does this is by trying to find parameters for a line that minimize the “error” or the “residuals” between the observed data, and the line. For example, here are examples of bad lines. The first assumes that all temperatures Celcius are basically 50°F. The other assumes that all temperatures in Farenheit are basically 3\(\times\)C.

Here is a plot of the best-fitting line, that has the smallest average residuals.

There are actually many different ways to figure out what the best line is (remembering that by “line” we really mean the pairing of Intercept and Slope). For example, one really simplistic approach1 would be just to draw a bunch of different lines, and see which one worked best.

However, there have been some long established methods for solving this problem, at is, for finding the one and truly best Intercept and Slope for a given set of data points.

Idiom

This isn’t R idiom, but stats idiom. Here are some translations for how people describe solving this problem.

  • analytic, closed form = “We solved it with complicated math.”
  • iterative, stochastic = “We made a bunch of guesses.”

For the sake of finishing the illustration, here is the solution that a linear regression found for this sample data:


Call:
lm(formula = f_observe ~ c_observe, data = temp_df)

Coefficients:
(Intercept)    c_observe  
     39.275        1.382  

The model has estimated that the Intercept is \(\approx\) 39 and the slope is \(\approx\) 1.4 . That is to say, based on our “sample”, it thinks 0°C = 39°F, and that every 1°C increase corresponds to a 1.4°F increase.

We are lucky to know that this is, strictly speaking, wrong, but we won’t usually, or typically, be able to in such a situation. However, the estimate of both the intercept and slope have the right sign (that is, it hasn’t guessed the intercept is -10, or the slope goes the other way), and they’re just about the right magnitude (that is, it hasn’t guessed that the slope is something like 10, or 100).

Now, let’s consider how the linear model is describing the value of this highlighted dot.

First, you take it’s value in Celcius, and multiply it by 1.3820366 (which is 28.47)

Then,you add 39.2752753 to it (which is 67.74)

Then, you add the residual error to give us the observed data point.

The generic formula for finding the value for any data point is

\[ F_i = 39.3 + (1.4\times C_i) + \epsilon_i. \] In this formula the \(i\) is convention for referring to some generic, \(i^{th}\) data point and \(\epsilon\) is conventional for referring to the residual errors.

Some additional conventions:

  • Referring to the outcome variable as \(y\).
  • Referring to the predictors as \(x\).
  • Referring to the remaining parameters as \(\beta\).

So you may sometimes see people referring to \(\beta_0\), or the “betas” in a model. The fully generic formula for linear regression is sometimes given as

\[ y_i = \beta_0 + \beta x_i + \epsilon_i \]

Idiom

  • We call the Intercept and Slopes the parameters or coefficients of the model.
  • For every data point, the value you get by only using the slopes and intercepts are called the fitted values, and they all lie along the lines you draw.
  • Almost every data point’s actual value is different from its fitted value, and these differences are called the residuals.

Understanding categorical predictors

Categorical variables are necessarilly treated differently in regression models. This is because while you can multiply numeric predictors together, you can’t multiply 5 \(\times\) “experimental condition”.

To illustrate how categorical predictors work in a linear regression, we’ll use some example weather data. I pulled this data of the daily temperature from the University of Edinburgh Geosciences Department weather station.

In order to focus on a categorical effect, I’ve recoded the date variable into “seasons” like so:

month season
Jan Winter
Feb Winter
Mar Spring
Apr Spring
May Spring
Jun Summer
Jul Summer
Aug Summer
Sep Autumn
Oct Autumn
Nov Autumn
Dec Winter

We’ll focus on just the subset of 2010 and 2011, because 2010 was a notably cold winter. Here’s all of the data for the four seasons from 2010 and 2011.

Winter is the “reference level”, for the season’s factor, which you can see if you use levels().

levels(temps_comp$season)
[1] "Winter" "Spring" "Summer" "Autumn"

When using treatment contrasts, the first level is always treated as the reference level.

If we fit a linear model to this data, we get the following solution:


Call:
lm(formula = temp ~ season, data = temps_comp)

Residuals:
     Min       1Q   Median       3Q      Max 
-11.5316  -1.7289   0.1078   1.8931  11.2572 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)    2.7283     0.2312   11.80   <2e-16 ***
seasonSpring   5.2934     0.3338   15.86   <2e-16 ***
seasonSummer  10.7282     0.3265   32.86   <2e-16 ***
seasonAutumn   6.9975     0.3293   21.25   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.102 on 698 degrees of freedom
Multiple R-squared:  0.6154,    Adjusted R-squared:  0.6137 
F-statistic: 372.2 on 3 and 698 DF,  p-value: < 2.2e-16

We’ve got a bunch of parameter estimates under “Estimate” and a bunch of significant p-values. But what does it mean to say “There is a significant effect of Spring”? And can we say anthing about, say, the difference between Spring and Autumn? Approach results that look like this exactly like you would a regression with continuous predictors: try to draw the graph it is a recipe for.

We start with the “Intercept”. With continuous predictors, the “intercept” is the y value where the line crosses 0 on the x-axis (a.k.a. the predicted value of the outcome variable when the predictor variable is 0). With categorical variables, there are no lines to draw to describe the relationship between outcome and predictor, so calling it an intercept is more of a metaphorical holdover of the continuous case.

Understand the “Intercept” for categorical predictors to be the predicted average of the reverence level. For the seasons model, the intercept is 2.73, meaning the estimated average winter temperature in Edinburgh is 2.73

Next, we move to the the Spring effect. Model estimates a Spring effect of 5.29. This is not the estimated temperature of Edinburgh in spring. This is how different the Spring temperature is from the Winter temperature. Meaning to get the estimated Spring temperature from the model we need to add the Spring effect to the intercept (2.73 + 5.29 = 8.02)

Next up is the Summer effect, which the model estimates is 10.73. Again, this is not the estimated temperature in the summer. This is how different Summer is estimated to be from the Intercept (Winter). To get the estimated Summer temperature from the model we need to add the Summer effect to the intercept (2.73 + 10.73 = 13.46).

And, what should seem familiar by now, the effect of Autumn is 7, meaning Autumn is 7 degrees warmer than Winter, meaning the estimated average temperature in Autumn is (2.73 + 7 = 9.73).

Let’s review the summary of the model again:

summary(season_model)

Call:
lm(formula = temp ~ season, data = temps_comp)

Residuals:
     Min       1Q   Median       3Q      Max 
-11.5316  -1.7289   0.1078   1.8931  11.2572 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)    2.7283     0.2312   11.80   <2e-16 ***
seasonSpring   5.2934     0.3338   15.86   <2e-16 ***
seasonSummer  10.7282     0.3265   32.86   <2e-16 ***
seasonAutumn   6.9975     0.3293   21.25   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.102 on 698 degrees of freedom
Multiple R-squared:  0.6154,    Adjusted R-squared:  0.6137 
F-statistic: 372.2 on 3 and 698 DF,  p-value: < 2.2e-16

We can say the following things about this model:

  • The significant (Intercept) effect means the average temperature in Winter is significantly different from 0 (estimated to be 2.7).
  • The significant seasonSpring effect means the difference between Spring and Winter is significantly different from 0 (Spring is estimated to be 5.3 degreees warmer than Winter.)
  • The significant seasonSummer effect means the difference between Summer and Winter is significantly different from 0 (Summer is estimated to be 10.7 degreees warmer than Winter.)
  • The significant seasonAutumn effect means the difference between Autumn and Winter is significantly different from 0 (Autumn is estimated to be 7 degreees warmer than Winter.)

And that is pretty much all we can say. Looking at these results, we can say that Spring is significantly warmer than Winter, but we can’t say anything about a generic “effect of Spring.” In fact, what would we mean by such a thing anyway?

We also can’t say anything about the difference between any of the other seasons. For example, Spring and Autumn have very similar looking temperatures (their difference from Winter is very similar). We can’t say anything about whether or not Spring is warmer or cooler than Autumn.

A more practical example - Scaling and transorming predictors

We’re now going to walk through a real example from my own research invovling the vowel /ay/. In this example, we’re going to be walking through

Brief Background on /ay/

The English vowel /ay/ is the vowel sound that appears in the English words ride and price. It is a “diphthong”, meaning it is a sound with two different articulatory targets. In the dialect this data is drawn from, the first target is something like a low and back [ɑ], which appears in the words hot and lot, and the second target is something like a high and front [i:], which shows up in the words fleece and heat. We’ll be focusing on just the first part of the diphthong, the typically low and back part.

Vowel sounds can be characterized using both articulatory and acoustic measures, and it has been found that certain acoustic features can be reliably correlated with the articulatory position of the tongue while the vowels are produced. This means we can characterize speakers’ pronunciations of vowel sounds from just a recording of their speech. If we examine how these acoustic properties of vowels covary with speakers’ ages or dates of birth, we can also estimate how pronunciations of these vowels have changed over time.

These acoustic properties are called “formants”, and the formant we are going focus on here is “F1”, which covaries with the height of the tongue in the mouth. The higher F1, the lower in the the mouth the tongue is. It’s also the case that F1 values systematically covary with the length of speakers’ vocal tracts, so we are actually going to be looking at normalized F1, which attempts to factor out this effect.

For this illustration, we’re going to first focus on the vowel /ay/ before voiceless consonants (i.e. /p, t, k, f, s/). In Philadelphia, where this data is from, /ay/ underwent a fairly large shift in its pronunciation across the 20th century.

ayT_means <- ay %>%
  filter(plt_vclass == "ay0" )%>%  # get the pre-voiceless tokens
  mutate(dob = year - age) %>%     # calculate speakers' dob
  group_by(idstring, dob) %>%      # prepare to estimate by-speaker means
  summarise(F1_n = mean(F1_n))     # means
ayT_means %>%
  ggplot(aes(dob, F1_n))+
    geom_point()+
    theme_bw()

In this plot, each point represents one speaker. Each speaker’s average normalized F1 value is plotted against their date of birth (ranging from 1889 to 1998). Fitting a linear model to this data appears easy, but actually poses us with interpretive challenges.

ayT_model1 <- lm(F1_n ~ dob, data = ayT_means)
summary(ayT_model1)

Call:
lm(formula = F1_n ~ dob, data = ayT_means)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.93874 -0.12952 -0.00738  0.12320  0.82237 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) 25.8100970  1.0232146   25.23   <2e-16 ***
dob         -0.0129710  0.0005262  -24.65   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2176 on 324 degrees of freedom
Multiple R-squared:  0.6522,    Adjusted R-squared:  0.6512 
F-statistic: 607.7 on 1 and 324 DF,  p-value: < 2.2e-16

Let’s sort out what is being reported here in this model, starting with the intercept.

              Estimate Std. Error t value Pr(>|t|)    
(Intercept) 25.8100970  1.0232146   25.23   <2e-16 ***

We see here that the intercept is significantly different from 0, but what does this intercept mean? The intercept is the estimated value of the outcome variable when the predictor is 0, meaning the model is predicting a value of normalized F1 of about 26 for speakers born in the year 0.

This is obviously problematic. First, this is a “significant” effect, but it extrapolates so far beyond the data that it’s entirely meaningless. (Nobody was speaking “English” in the year 0.) Second, this estimated normalized F1 value is not a plausible F1 value for any vowel. If you were to try to map this onto an articulatory strategy, speaker’s tongue bodies would be down somewhere around their ankles.

Let’s also look at the slope.

              Estimate Std. Error t value Pr(>|t|)    
dob         -0.0129710  0.0005262  -24.65   <2e-16 ***

This means for every 1 unit increase in dob (i.e. 1 year), there is a decrease of -0.013 in normalized F1.

If we ignore the comically weird intercept, this slope is less problematic. The one major issue in it is its overspecificity. This slope is defined in terms of a change in 1 year of date of birth, but in an important sense that’s over precise. We wouldn’t really want to make any strong inferences about the difference between speakers’ born in 1969 and 1970, for example.

Rescaling

We can address these problems with the modekl by rescaling the date of birth predictor. Rescaling predictors is not only “allowed,” it can be crucial when it comes to trying to fit mixed effects models!

Idiom

Not to confuse things too much, but transormations you make to predictors can be lumped into two broad categories: linear and non-linear. This use of “linear” isn’t related to linear regression in any way. Instead, it describes the relationship between the original measure and the transformed measure.

Linear transformations are:

  • addition, subtraction, multiplication, division

Proof by simulation:

linear_df <- data_frame(original = rnorm(100, mean = 50),
                        addition = original + 10,
                        subtraction = original - 10,
                        multiplication = original * 10,
                        division = original/10)

Any combination of (only) linear transforms is a linear transform.

Non-linear transformations are:

  • logarithms (any base), cosine, square root, etc.

Proof by simulation:

nonlinear_df <- data_frame(original = rnorm(100, mean = 5),
                           log_ten = log10(original),
                           cosine = cos(original),
                           square_root = sqrt(original),
                           exponential = exp(original))

If we apply one, or many, linear transformations to the predictor variable, we won’t affect the goodness of fit of the model, nor the significance or sign of that predictor. But it will change the way we interpret the effects.

There are a few different kinds of transformations we can do. A very common kind of transformation is to z-score the data. To z-score numeric data, you subtract the mean and divide by the standard deviation. Here’s how that looks in mathematical notation

\[ z = \frac{x-\mu}{\sigma} \]

Where \(\mu\) is the mean of the \(x\) data, and \(\sigma\) is the standard deviation. Here’s how that looks in practice. The date of birth of speakers has the following distribution of data, with the meand and \(\pm1\) standard deviation annotated.

By subtracting out the mean, we center this distribution on 0, and by dividing by the standard deviation, we shrink down the distribution so that 1 standard deviation from the mean is the value 1. Here’s how the result looks:

Why is this an improvement?

Let’s re-fit the model with this transformed DOB predictor and see:

ayT_model2 <- lm(F1_n ~ dob_z, data = ayT_means)
summary(ayT_model2)

Call:
lm(formula = F1_n ~ dob_z, data = ayT_means)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.93874 -0.12952 -0.00738  0.12320  0.82237 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.58862    0.01205   48.83   <2e-16 ***
dob_z       -0.29760    0.01207  -24.65   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2176 on 324 degrees of freedom
Multiple R-squared:  0.6522,    Adjusted R-squared:  0.6512 
F-statistic: 607.7 on 1 and 324 DF,  p-value: < 2.2e-16
            Estimate Std. Error t value Pr(>|t|)
(Intercept)  0.58862    0.01205   48.83   <2e-16 ***

The intercept is the estimated value of normalized F1 when dob_z is 0, which is the mean of dob, 1944.

            Estimate Std. Error t value Pr(>|t|)
dob_z       -0.29760    0.01207  -24.65   <2e-16 ***

The slope tells us how much normalized F1 changes for every change of 1 standard deviation of dob (23 years)

For every 1 standard deviation shift in dob (23 years), there is a decrease of 0.3 in normalized F1.

These values of the intercept and slope are more interpretable.

Other possible transformations

The z-score transformation isn’t the only transformation you can use. It’s just the most standard one. For example, Gelman & Hill (200XX) recommend using a modified z-score where you divide by \(2\times\sigma\)

\[ z = \frac{x-\mu}{2\sigma} \]

The reason these formulas use the mean and standard deviation is because they are two theory neutral values that can be estimated for any set of numeric data. However, it’s possible that there are more sensible scaling factors for the data you’re working with. For example, in many sociolinguistic studies, the year 1960 is an important inflection point for many changes. And 23 years doesn’t have any intrinsic meaning, while something like 10 years is more intuitively accessible to most readers (“a decade”). So we could just as easilly choose this scaling formula for date of birth.

\[ decade = \frac{x - 1960}{10} \]

Are we really allowed to do all this rescaling?

Yes, but, you must explain what you did in the write up. For example:

The date of birth predictor was centered on 1960, and divided by 10. The 1960 was chosen as the centering point because of its importance in previous sociolinguistic studies. Dividing dob by 10 gives the resulting slope the interpretation of the rate of change per decade.

Multivariate Models & Interactions

We’re quickly going to go over multivariate models (multiple predictors) and interactions. The important thing to keep in mind when including multiple predictor is that your reference level and scaling of each predictor is going to start to matter a lot more.

Continious and categorical predictors

Let’s start with the /ay/ data. Previously we were looking only at pre-voiceless /ay/. But now we’re going to look at all /ay/, with each token coded for whether it’s pre-voiceless, or elsewhere. This is encoded in the plt_vclass column.

  • plt_vclass
    • ay0 - Pre-voiceless /ay/
    • ay - All other /ay/.

Because we’re not dealing with mixed effects models yet, we’ll first calculate by-speaker means. In the process I’ll be re-scaling date of birth with two differing centering points, one on 1900, and one on 1960.

ay_means <- ay %>%
              mutate(dob = year-age) %>%
              group_by(idstring, dob, plt_vclass) %>%
              summarise(F1_n = mean(F1_n))%>%
              mutate(decade_1900 = (dob - 1900)/10,
                     decade_1960 = (dob - 1960)/10,
                     voicing = factor(recode(plt_vclass, ay0 = "voiceless",
                                                         ay = "else")),
                     voicing = relevel(voicing, "else"))
ggplot(ay_means, aes(dob, F1_n, color = voicing))+
    geom_point()+
    theme_bw()

Two predictors, no interactions

We can see that there is a big difference between pre-voiceless and elsewhere /ay/. Let’s start building up the model then

ay_model1 <- lm(F1_n ~ decade_1900 + voicing, data = ay_means)
summary(ay_model1)

Call:
lm(formula = F1_n ~ decade_1900 + voicing, data = ay_means)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.01218 -0.14438 -0.01086  0.13725  0.77522 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)       1.567577   0.020862   75.14   <2e-16 ***
decade_1900      -0.075493   0.003793  -19.91   <2e-16 ***
voicingvoiceless -0.643357   0.017376  -37.02   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2218 on 649 degrees of freedom
Multiple R-squared:  0.7314,    Adjusted R-squared:  0.7305 
F-statistic: 883.5 on 2 and 649 DF,  p-value: < 2.2e-16

Let’s walk through the effects by drawing the graph that this model is a recipe for. First, we have the Intercept.

                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)       1.567577   0.020862   75.14   <2e-16 ***

This is the estimated average value of normalized F1 for when all predictors are 0. That means this is the predicted intercept when the centered dob is 0 (1900), for the reference level (elsewhere /ay/)

Next there’s the slope:

                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)       1.567577   0.020862   75.14   <2e-16 ***

There’s a few different ways we could construe this slope. The value is the rate of change per decade, and we’ll interpret this as the slope for reference level.

Finally, there’s the voicing parameter.

                  Estimate Std. Error t value Pr(>|t|)    
voicingvoiceless -0.643357   0.017376  -37.02   <2e-16 ***

This tells us how different the intercept of the line for pre-voiceless /ay/ is from elsewhere /ay/. Because we have included no other effects or interactions, the model is assuming that the slope of the pre-voiceless /ay/ is identical to elsewhere /ay/.

Note, looking a this graph, you can see that this voiceless effect is not the estimated intercept of pre-voicelss /ay/. It is the estimated difference in intercepts between these two lines.

Evaluating the model.

Let’s look at the model summary again:

summary(ay_model1)

Call:
lm(formula = F1_n ~ decade_1900 + voicing, data = ay_means)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.01218 -0.14438 -0.01086  0.13725  0.77522 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)       1.567577   0.020862   75.14   <2e-16 ***
decade_1900      -0.075493   0.003793  -19.91   <2e-16 ***
voicingvoiceless -0.643357   0.017376  -37.02   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2218 on 649 degrees of freedom
Multiple R-squared:  0.7314,    Adjusted R-squared:  0.7305 
F-statistic: 883.5 on 2 and 649 DF,  p-value: < 2.2e-16

If you only fit this model, and didn’t plot any of the data, you might conclude:

  • There is a significant change over decade for /ay/.
  • There is a significant effect of voicing on /ay/.

Including interactions

However, looking at the plot, it’s clear something more complicated is going on. Neither of the lines look like they’re passing through their related data points very well. There is, in fact, an interaction between voicing and date of birth. Pre-voiceless /ay/ is undergoing a change, while elsewhere /ay/ is basically staying the same. We can account for this by including this interaction in the model:

ay_model2 <- lm(F1_n ~ decade_1900 * voicing, data = ay_means)
summary(ay_model2)

Call:
lm(formula = F1_n ~ decade_1900 * voicing, data = ay_means)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.93874 -0.11050 -0.00824  0.10554  0.82237 

Coefficients:
                              Estimate Std. Error t value Pr(>|t|)    
(Intercept)                   1.326564   0.022219  59.703  < 2e-16 ***
decade_1900                  -0.021277   0.004443  -4.789 2.08e-06 ***
voicingvoiceless             -0.161329   0.031423  -5.134 3.75e-07 ***
decade_1900:voicingvoiceless -0.108433   0.006283 -17.257  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1838 on 648 degrees of freedom
Multiple R-squared:  0.816, Adjusted R-squared:  0.8151 
F-statistic: 957.6 on 3 and 648 DF,  p-value: < 2.2e-16

Let’s build up the graph.

                              Estimate Std. Error t value Pr(>|t|)    
(Intercept)                   1.326564   0.022219  59.703  < 2e-16 ***

This is the estimated average for when all preditors are 0 (i.e. dob = 1900, voicing = else).

                              Estimate Std. Error t value Pr(>|t|)    
decade_1900                  -0.021277   0.004443  -4.789 2.08e-06 ***

This is the estimated slope for the reference level (i.e. voicing = else)

Now, we get into the more complicated coefficients.

                              Estimate Std. Error t value Pr(>|t|)    
voicingvoiceless             -0.161329   0.031423  -5.134 3.75e-07 ***

This is how different the line for pre-voiceless /ay/ is from elsewhere /ay/ at the intercept (i.e. when dob = 1900).

Finally, we have the interaction effect.

                              Estimate Std. Error t value Pr(>|t|)    
decade_1900:voicingvoiceless -0.108433   0.006283 -17.257  < 2e-16 ***

This is the most easilly misinterpretable parameter in this model. It is not the estimated slope of pre-voiceless /ay/. It is how different pre-voiceless /ay/’s slope is from elsewhere /ay/. That is, if you drew a line parallel to elsewhere /ay/, thos is how much you’d have to rotate the the line to get pre-voiceless /ay/’s slope.

Be careful thinking about models with interactions

This is super important to keep in mind, let’s say we ran this model, and got the following coefficients:

(Intercept)                   1.32    ***
decade_1900                  -10      ***
voicingvoiceless             -0.16    ***
decade_1900:voicingvoiceless  10      ***

The significant interaction between date of birth and voicing here would not mean that there is significant change for pre-voiceless /ay/ over time. It means there is a significant difference between the slope of elsewhere /ay/ and pre-voiceless /ay/. The estimated slope of elsewhere /ay/ in this fake model is -10, and for pre-voiceless /ay/ it’s -10 + 10 = 0!

The other thing to keep in mind with interpreting the results of the model is that the voicingvoiceless effect is not an estimate of “the effect of voicing.” It is the estimated difference between the two lines at the intercept. If we change where the intercept is, for example by using a different scaling, we also change the value of this parameter.

summary(lm(F1_n ~ decade_1900 * voicing, data = ay_means))

Call:
lm(formula = F1_n ~ decade_1900 * voicing, data = ay_means)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.93874 -0.11050 -0.00824  0.10554  0.82237 

Coefficients:
                              Estimate Std. Error t value Pr(>|t|)    
(Intercept)                   1.326564   0.022219  59.703  < 2e-16 ***
decade_1900                  -0.021277   0.004443  -4.789 2.08e-06 ***
voicingvoiceless             -0.161329   0.031423  -5.134 3.75e-07 ***
decade_1900:voicingvoiceless -0.108433   0.006283 -17.257  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1838 on 648 degrees of freedom
Multiple R-squared:  0.816, Adjusted R-squared:  0.8151 
F-statistic: 957.6 on 3 and 648 DF,  p-value: < 2.2e-16
summary(lm(F1_n ~ decade_1960 * voicing, data = ay_means))

Call:
lm(formula = F1_n ~ decade_1960 * voicing, data = ay_means)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.93874 -0.11050 -0.00824  0.10554  0.82237 

Coefficients:
                              Estimate Std. Error t value Pr(>|t|)    
(Intercept)                   1.198902   0.012301  97.467  < 2e-16 ***
decade_1960                  -0.021277   0.004443  -4.789 2.08e-06 ***
voicingvoiceless             -0.811927   0.017396 -46.674  < 2e-16 ***
decade_1960:voicingvoiceless -0.108433   0.006283 -17.257  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1838 on 648 degrees of freedom
Multiple R-squared:  0.816, Adjusted R-squared:  0.8151 
F-statistic: 957.6 on 3 and 648 DF,  p-value: < 2.2e-16

With the date of birth centered on 1900, we get a relatively weak effect (-0.16). With the date of birth centered on 1960, we get a much stronger effect (-0.81). That’s because there is a strong interaction between the date of birth and voicing context, and there is a bigger difference between these two lines in 1960 than in 1900!

It is, in fact, more than possible for a predictor like this to have an estimated value close to 0, and be non-significant, but for it to actuallty matter a lot to the model.

Lessons

  • Always think carefully about the meaning of predictors in a model with interactions.
  • Always try to draw the graph out.
  • Always remember the parameters are estimates of the difference from the reference levels.
  • Non-significant != not important.

Categorical interactions.

We’ll return to the weather data to examine the interpretation of categorical interactions. We’ll be using season and a categorical coding of year.

temps_comp <- temps_comp %>%
                  mutate(year_factor = factor(year))

Fitting the model is straight forward.

temps_model <- lm(temp ~ season * year_factor, data = temps_comp)
summary(temps_model)

Call:
lm(formula = temp ~ season * year_factor, data = temps_comp)

Residuals:
    Min      1Q  Median      3Q     Max 
-10.336  -1.744   0.041   1.726  11.898 

Coefficients:
                             Estimate Std. Error t value Pr(>|t|)    
(Intercept)                    1.2151     0.3092   3.929 9.37e-05 ***
seasonSpring                   6.1661     0.4603  13.395  < 2e-16 ***
seasonSummer                  12.7472     0.4385  29.067  < 2e-16 ***
seasonAutumn                   7.3150     0.4451  16.436  < 2e-16 ***
year_factor2011                3.0264     0.4373   6.920 1.03e-11 ***
seasonSpring:year_factor2011  -1.8707     0.6333  -2.954  0.00324 ** 
seasonSummer:year_factor2011  -4.0215     0.6176  -6.511 1.43e-10 ***
seasonAutumn:year_factor2011  -0.7270     0.6231  -1.167  0.24375    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.934 on 694 degrees of freedom
Multiple R-squared:  0.6579,    Adjusted R-squared:  0.6545 
F-statistic: 190.7 on 7 and 694 DF,  p-value: < 2.2e-16

There’s a lot going on here, and it is very easy to misinterpret the results if you don’t try to draw out the graph. We’ll take the coefficients in batches. First, there is the “intercept.”

                             Estimate Std. Error t value Pr(>|t|)    
(Intercept)                    1.2151     0.3092   3.929 9.37e-05 ***

This is the estimated average temperature for the references levels, that is, for season = Winter, year = 2010.

Next, there are the season effects.

                             Estimate Std. Error t value Pr(>|t|)    
seasonSpring                   6.1661     0.4603  13.395  < 2e-16 ***
seasonSummer                  12.7472     0.4385  29.067  < 2e-16 ***
seasonAutumn                   7.3150     0.4451  16.436  < 2e-16 ***

Recall, these are the estimated differences between Winter and the named season. But because there is an interaction effect between season and year, these values are even more specific: these are the estimated differences between each of these named seasons and Winter in 2010, because 2010 is the reference level for year.

Next is the year effect

                             Estimate Std. Error t value Pr(>|t|)    
year_factor2011                3.0264     0.4373   6.920 1.03e-11 ***

Again, because there is an interaction effect between season and year, this is estimated difference between Winter 2010 and Winter 2011. I’m drawing this on the graph for winter in a solid line, and for all of the other seasons in a dashed line. As will be made clear in a moment, this is is because the interaction effects can only be interpreted in relation to these dashed lines.

Finally, there are the interation terms!

                             Estimate Std. Error t value Pr(>|t|)    
seasonSpring:year_factor2011  -1.8707     0.6333  -2.954  0.00324 ** 
seasonSummer:year_factor2011  -4.0215     0.6176  -6.511 1.43e-10 ***
seasonAutumn:year_factor2011  -0.7270     0.6231  -1.167  0.24375    

The effect of year in the model was about 3, meaning Winter 2011 was 3 degrees warmer than Winter 2010. If we look at the Spring:Year interaction here, it has a value of -1.9, meaning Spring 2011 was 3-1.9 = 1.1 degree warmer than Spring 2010.

That is, these interaction terms are telling us how different the year effect for each season is from the year effect for Winter, our reference level. Just because Spring:2011 has a significant negative value doesn’t mean Spring 2011 was colder than Spring 2010! It just means that the difference between Spring 2010 and Spring 2011 was not as big as that between Winter 2010 and Winter 2011!

The significant Spring:2011 effect also does not mean that Spring 2011 was a significantly different temperature than Spring 2010!

Next Week

  • Introducing Mixed Effects Models

  1. Actually, this “simplistic approach” is more like the sophisticated approach these days, because there are complicated maths behind making good guesses which are given semantically opaque names like “Simulated Annealing” and “Hamiltonian Monte Carlo”.

LS0tCnRpdGxlOiAiSW50cm8gJiBSZXZpZXdpbmcgTGluZWFyIE1vZGVscyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogbm9uZQogICAgY3NzOiAuLi9jdXN0b20uY3NzCiAgICB0aGVtZTogZmxhdGx5CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19kZXB0aDogMwotLS0KCiMgQWdlbmRhCgoxLiBJbnRyb2R1Y3Rpb25zCjIuIENvdXJzZSBBZG1pbgozLiBTZXR1cAo0LiBSZXZpZXdpbmcgdGhlIG1vc3QgaW1wb3J0YW50IHBhcnRzIG9mIExpbmVhciBNb2RlbHMKCgojIEludHJvZHVjdGlvbnMKCjxkaXYgY2xhc3MgPSAiYm94IGJyZWFrIj4KPHNwYW4gY2xhc3MgPSAiYmlnLWxhYmVsIj5IZWxsbyE8L3NwYW4+CgpNeSBuYW1lIGlzIEpvc2VmIEZydWVod2FsZCwgYW5kIEknbSBhIGxlY3R1cmVyIGluIExpbmd1aXN0aWNzIGFuZCBFbmdsaXNoIExhbmd1YWdlLgoKPC9kaXY+CgpJbiB0aGlzIGZpcnN0IGJsb2NrIG9mIG11bHRpdmFyaWF0ZSBzdGF0cywgd2UnbGwgYmUgY292ZXJpbmcKCi0gVGhlIHJlYXNvbnMgd2h5IHlvdSBzaG91bGQgZml0IExpbmVhciBNaXhlZCBFZmZlY3RzIG1vZGVscy4KLSBIb3cgdG8gZml0IExNTXMuCi0gSG93IHRvIGludGVycHJldCB0aGUgcmVzdWx0cyBvZiBMTU1zLgotIEhvdyB0byBkbyBtb2RlbCBjb21wYXJpc29uICYgcGFyYW1ldGVyIGV2YWx1YXRpb24uCi0gSG93IHRvIHJlcG9ydCB0aGUgcmVzdWx0cyBvZiB5b3VyIExNTXMuCi0gU29tZSBwcmFnbWF0aWMgaXNzdWVzIGluIHRoaW5raW5nIGFib3V0IHlvdXIgcmVzdWx0cy4KCkluIHRoZSBsYWIgc2Vzc2lvbnMsIHlvdSdsbCB3b3JrIHRocm91Z2ggZXhlcmNpc2VzIHJlbGF0ZWQgdG8gZml0dGluZyBMTU1zLCBhcyB3ZWxsIGFzIHJlbGF0ZWQgUiBwcm9ncmFtbWluZyBza2lsbHMgcmVsYXRlZCB0byBkYXRhIG9yZ2FuaXphdGlvbiBhbmQgdmlzdWFsaXphdGlvbi4KCiMgQ291cnNlIEFkbWluCgpBbGwgbGVjdHVyZXMgd2lsbCBpbmNsdWRlIHNvbWUgUiBwcm9ncmFtbWluZyB5b3UgY2FuIGRvIGR1cmluZyB0aGUgbGVjdHVyZS4gSSdsbCByZWNvbW1lbmQgdGhhdCB5b3UgY3JlYXRlIGEgZnJlc2ggUiBOb3RlYm9vayBmb3IgZWFjaCBsZWN0dXJlLgoKPGRpdiBjbGFzcyA9ICJib3ggYnJlYWsiPgo8c3BhbiBjbGFzcyA9ICJiaWctbGFiZWwiPn41IE1pbnV0ZSBTZXR1cDwvc3Bhbj4KCkZpcnN0IGNyZWF0ZSBhIG5ldyBSIE5vdGVib29rIGZvciB0aGlzIGxlY3R1cmUgd2l0aCBgRmlsZSA+IE5ldyBGaWxlID4gUiBOb3RlYm9va2AuIEkgd291bGQgcmVjb21tZW5kIGNoYW5naW5nIHRoZSB0b3AgaGVhZGVyIG1ldGFkYXRhIHNvIGl0IGhhcyBhIG1lYW5pbmdmdWwgdGl0bGU6CgpgYGAKLS0tCnRpdGxlOiAiTXVsdGl2YXJpYXRlIC0gTGVjdHVyZSAxIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmBgYAoKRGVsZXRlIGV2ZXJ5dGhpbmcgZWxzZSBpbiB0aGUgbm90ZWJvb2suCgo8aHI+CgpOb3csIGxldCdzIGluc3RhbGwgc29tZSBwYWNrYWdlcyB0aGF0IHdpbGwgYmUgbmVjZXNzYXJ5IGluIHRoZXNlIGxlY3R1cmVzOgoKCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKAogIGMoInRpZHl2ZXJzZSIsCiAgICAiZGV2dG9vbHMiLAogICAgImxtZTQiKQopCgpsaWJyYXJ5KCJkZXZ0b29scyIpCgppbnN0YWxsX2dpdGh1Yigiam9mcmh3bGQvbXVsdGl2YXJpYXRlMjAxNyIpCgpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsbWU0KQpsaWJyYXJ5KG11bHRpdmFyaWF0ZTIwMTcpCmBgYAoKCgo8L2Rpdj4KCgo8ZGl2IGNsYXNzID0gImJveCBoeWdpZW5lIj4KPHNwYW4gY2xhc3MgPSAibGFiZWwiPldvcmtzcGFjZSBIeWdpZW5lPC9zcGFuPgoKIyMgUmVjb21tZW5kZWQgQ291cnNlIERpcmVjdG9yeSBTdHJ1Y3R1cmUKCklmIHlvdSBoYXZlIGEgZGlyZWN0b3J5IHBsYW5uaW5nIHN0cnVjdHVyZSB0aGF0IHlvdSdyZSBoYXBweSB3aXRoLCBnbyBhaGVhZCBhbmQgZG8gdGhhdC4gQnV0IEknZCByZWNvbW1lbmQgdGhlIGZvbGxvd2luZyBkaXJlY3Rvcnkgc3RydWN0dXJlICYgbmFtaW5nIGNvbnZlbnRpb25zLgoKICAgIOKUnOKUgOKUgCBtdWx0aXZhcmlhdGVfMjAxNwogICAg4pSCwqDCoCDilJTilIDilIAgbG1tCiAgICDilILCoMKgIOKUgsKgwqAg4pSU4pSA4pSAIGFzc2Vzc21lbnQKICAgIOKUgsKgwqAg4pSCwqDCoCDilJTilIDilIAgZGF0YQogICAg4pSCwqDCoCDilILCoMKgIOKUlOKUgOKUgCBsYWJzCgpGb3IgYSBnb29kIHBoaWxvc29waHkgb24gbmFtaW5nIGZpbGVzLCBJJ2QgcmVjb21tZW5kIFt0aGVzZSBzbGlkZXMgZnJvbSBKZW5ueSBCcnlhbidzIHRhbGsgb24gTmFtaW5nIFRoaW5nc10oaHR0cDovL3d3dzIuc3RhdC5kdWtlLmVkdS9+cmNzNDYvbGVjdHVyZXNfMjAxNS8wMS1tYXJrZG93bi1naXQvc2xpZGVzL25hbWluZy1zbGlkZXMvbmFtaW5nLXNsaWRlcy5wZGYpCgpBbHNvIGdvb2QgcHJhY3RpY2UgaXMgdG8gbG9hZCBhbGwgdGhlIHBhY2thZ2VzIHlvdSdyZSBnb2luZyB0byBuZWVkIGF0IHRoZSAqdG9wKiBvZiB5b3VyIHNjcmlwdC9ub3RlYm9vayBpbiBvbmUgYmxvY2ssIHJhdGhlciB0aGFuIGhhcGhhemFyZGx5IHRocm91Z2hvdXQuCgo8L2Rpdj4KCgojIFRoZSBQbGFuIEZvciBUaGlzIFdlZWsKCiMjIExlY3R1cmUKClRvZGF5LCB3ZSdyZSBnb2luZyB0byBnb2luZyB0byByZXZpZXcgdGhlIGVzdGltYXRpb24gJiBpbnRlcnByZXRhdGlvbiBvZiBsaW5lYXIgbW9kZWxzLCB3aXRoIGEgZm9jdXMgb246CgotIHRoZSBzY2FsaW5nICYgdHJhbnNmb3JtYXRpb24gb2YgcHJlZGljdG9ycwotIHRoZSBzZWxlY3Rpb24gb2YgY29udHJhc3RzCi0gdGhlIGludGVycHJlYXRpb24gb2YgaW50ZXJhY3Rpb24gZWZmZWN0cwoKIyMgTGFicwoKVGhlIGxhYiBleGVyY2lzZXMgdGhpcyB3ZWVrIHdpbGwgZm9jdXMgb24gZGF0YSAocmUpb3JnYW5pemF0aW9uIGFuZCB2aXp1YWxpemF0aW9uLgoKCiMgVW5kZXJzdGFuZGluZyBMaW5lYXIgUmVncmVzc2lvbgoKCgpJIGZpbmQgdGhlIGJlc3Qgd2F5IHRvIHVuZGVyc3RhbmQgbGluZWFyIHJlZ3Jlc3Npb25zIGlzIGFzIHJlY2lwZXMgZm9yIGRyYXdpbmcgYSBncmFwaC4gTGV0J3Mgc3RhcnQgb2ZmIHdpdGggYW4gZXhhbXBsZSByZWxldmFudCB0byBteSBvd24gbGlmZTogdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRlbXBlcmF0dXJlcyBpbiBDZWxjaXVzIGFuZCB0ZW1wZXJhdHVyZXMgaW4gRmFyZW5oZWl0LiBUaGVyZSBhcmUgdHdvIGltcG9ydGFudCBudW1lcmljIGNvbnN0YW50cyB0byBjb252ZXJ0IGJhY2sgYW5kIGZvcnRoIGJldHdlZW4gdGhlbToKCjEuIEZyZWV6aW5nID0gMCYjMTc2O0MgPSAzMiYjMTc2O0YKMi4gQSBjaGFuZ2Ugb2YgMSYjMTc2O0MgPSAxLjgmIzE3NjtGCgoKVGhpcyBnaXZlcyB1cyBhbGwgb2YgdGhlIG5lY2Vzc2FyeSBjb21wb25lbnRzIGZvciBkcmF3aW5nIGEgZ3JhcGggb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIEZhcmVuaGVpdCBhbmQgQ2VsY2l1cy4gRmlyc3QsIHdlIGtub3cgdGhhdCBhIGxpbmUgcGxvdHRpbmcgdGhpcyByZWxhdGlvbnNoaXAgbXVzdCBjcm9zcyAwIG9uIHRoZSB4LWF4aXMgYXQgMzIgb24gdGhlIHktYXhpcywgYmVjYXVzZSBmcmVlemluZyA9IDAmIzE3NjtDID0gMzImIzE3NjtGLgoKCmBgYHtyIGVjaG8gPSBGfQpsaWJyYXJ5KGdyaWQpCmdncGxvdCgpKwogIHhsaW0oLTMsIDQwKSsKICB5bGltKDAsIDQwKSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBhbm5vdGF0ZShnZW9tID0gInNlZ21lbnQiLCB4ID0gMCwgeSA9IDAsIHhlbmQgPSAwLCB5ZW5kID0gMzIsCiAgICAgICAgICAgc2l6ZSA9IDEsIGFycm93ID0gYXJyb3coKSkrCiAgYW5ub3RhdGUoZ2VvbSA9ICJwb2ludCIsIHggPSAwLCB5ID0gMzIsIGNvbG9yID0gJ3JlZCcpKwogIHhsYWIoIkNlbGNpdXMiKSsKICB5bGFiKCJGYXJlbmhlaXQiKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgY29vcmRfZml4ZWQoKQpgYGAKCk5leHQsIHdlIGtub3cgdGhhdCBmb3IgMSBldmVyeSBkZWdyZWUgd2UgbW92ZSB0byB0aGUgcmlnaHQsIHdlIG11c3QgbW92ZSB1cCAxLjguCgpgYGB7ciBlY2hvID0gRn0KCmZjIDwtIGRhdGFfZnJhbWUoY2VsY2l1cyA9IGMoMCwgMSwgMiwgMywgNCksCiAgICAgICAgICAgICAgICAgRmFyZW5oZWl0ID0gKGNlbGNpdXMgKiAxLjgpICsgMzIpCgpnZ3Bsb3QoZmMpKwogIHhsaW0oLTMsIDQwKSsKICB5bGltKDAsIDQwKSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBhbm5vdGF0ZShnZW9tID0gInNlZ21lbnQiLCB4ID0gMCwgeSA9IDAsIHhlbmQgPSAwLCB5ZW5kID0gMzIsCiAgICAgICAgICAgc2l6ZSA9IDEsIGFycm93ID0gYXJyb3coKSkrCiAgZ2VvbV9zdGVwKGFlcyh4ICA9IGNlbGNpdXMsIHkgPSBGYXJlbmhlaXQpKSsgIAogIGdlb21fcG9pbnQoYWVzKHggID0gY2VsY2l1cywgeSA9IEZhcmVuaGVpdCksIAogICAgICAgICAgICAgY29sb3IgPSAncmVkJykrCiAgeGxhYigiQ2VsY2l1cyIpKwogIHlsYWIoIkZhcmVuaGVpdCIpKwogIHRoZW1lX21pbmltYWwoKSsKICBjb29yZF9maXhlZCgpCmBgYAoKVGhlIGxpbmUsIHJlcHJlc2VudGluZyB0aGlzIHJlbGF0aW9uc2hpcCwgdGh1cyBoYXMgdGhlIGZvcm11bGE6CgokJAp5ID0gMzIgKyAoMS44XHRpbWVzIHgpCiQkCgpBbmQgbG9va3MgbGlrZQoKYGBge3IgZWNobyA9IEZ9CgpnZ3Bsb3QoZmMpKwogIHhsaW0oLTMsIDYwKSsKICB5bGltKDAsIDYwKSsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICBhbm5vdGF0ZShnZW9tID0gInNlZ21lbnQiLCB4ID0gMCwgeSA9IDAsIHhlbmQgPSAwLCB5ZW5kID0gMzIsCiAgICAgICAgICAgc2l6ZSA9IDEsIGFycm93ID0gYXJyb3coKSkrCiAgZ2VvbV9zdGVwKGFlcyh4ICA9IGNlbGNpdXMsIHkgPSBGYXJlbmhlaXQpKSsgIAogIGdlb21fcG9pbnQoYWVzKHggID0gY2VsY2l1cywgeSA9IEZhcmVuaGVpdCksIAogICAgICAgICAgICAgY29sb3IgPSAncmVkJykrCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMzIsIHNsb3BlID0gMS44LCBjb2xvciA9ICdyZWQnKSsKICB4bGFiKCJDZWxjaXVzIikrCiAgeWxhYigiRmFyZW5oZWl0IikrCiAgdGhlbWVfbWluaW1hbCgpKwogIGNvb3JkX2ZpeGVkKCkKYGBgCgpUaGlzIGxpbmUgaGFzIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllczoKCjEuIEl0cyAqKkludGVyY2VwdCoqLCBvciB3aGVyZSB0aGUgbGluZSBjcm9zc2VzIDAgb24gdGhlIHgtYXhpcywgaXMgMzIuCjIuIEl0cyAqKlNsb3BlKiosIGlzIDEuOCAodGhhdCBpcywgYSBjaGFuZ2Ugb2YgMSBvbiB0aGUgeC1heGlzIGNvcnJlc3BvbmRzIHRvIGEgY2hhbmdlIGluIDEuOCBvbiB0aGUgeS1heGlzKQoKCkFuZCwgaW4gZmFjdCwgKmFsbCogbGluZXMsIGluY2x1ZGluZyB0aGUgb25lcyB3ZSBmaXQgdXNpbmcgbGluZWFyIHJlZ3Jlc3Npb24sIGFyZSBkZXNjcmliZWQgaW4gdGVybXMgb2YgdGhlaXIgaW50ZXJjZXB0ICh3aGVyZSB0aGUgbGluZSBjcm9zc2VzIDAgb24gdGhlIHgtYXhpcykgYW5kIHNsb3BlLgoKCkJ1dCwgbGV0J3Mgc2F5IHlvdSBkaWRuJ3Qga25vdyB0aGUgZm9ybXVsYSB0byBjb252ZXJ0IGJhY2sgYW5kIGZvcnRoIGJldHdlZW4gQ2VsY2l1cyBhbmQgRmFyZW5oZWl0LiBNYXliZSB5b3Ugd2VyZW4ndCBldmVuIHN1cmUgdGhhdCB0aGVyZSB3YXMgc3VjaCBhIGZvcm11bGEuIEFuZCBhbGwgeW91IGhhZCB3ZXJlIGEgYnVuY2ggb2Yga2luZCBvZiBjcmFwcHkgdGhlcm1vbWV0ZXJzIHRoYXQgZ2F2ZSB5b3UgYm90aCBDZWxjaXVzIGFuZCBGYXJlbmhlaXQgcmVhZGluZ3MuIEFuZCBtYXliZSB0aGUgdGhlcm1vbWV0ZXJzIGFyZSBraW5kIG9mIGhhcmQgdG8gcmVhZCwgb3IgdGhlIGxpZ2h0aW5nIGNvbmRpdGlvbnMgYXJlIGRhcmssIG9yIHlvdSBvbmx5IGhhdmUgbGltaXRlZCBleHBlcmllbmNlIGluIHJlYWRpbmcgdGhlcm1vbWV0ZXJzLiBJbiB0aGF0IGNhc2UsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBDZWxjaXVzIGFuZCBGYXJlbmhlaXQgbWlnaHQgbG9vayBhIGxvdCBtb3JlIGxpa2UgdGhpczoKCmBgYHtyLCBlY2hvID0gRn0KdHJ1ZV9jIDwtIGMoMCwgMTAsIDE2LCAyMCwgMjMsIDMwKQp0cnVlX2YgPC0gKHRydWVfYyoxLjgpICsgMzIKY19vYnNlcnZlIDwtIG1hcCh0cnVlX2MsIH5ybm9ybSgyMCwgbWVhbiA9IC54LCBzZCA9IDUpKSAlPiUgc2ltcGxpZnkoKQpmX29ic2VydmUgPC0gbWFwKHRydWVfZiwgfnJub3JtKDIwLCBtZWFuID0gLngsIHNkID0gNSoxLjgpKSAlPiUgc2ltcGxpZnkoKQoKdGVtcF9kZiA8LSBkYXRhLmZyYW1lKGNfb2JzZXJ2ZSA9IGNfb2JzZXJ2ZSwKICAgICAgICAgICAgICAgICAgICAgIGZfb2JzZXJ2ZSA9IGZfb2JzZXJ2ZSkKCgp0ZW1wX2RmICU+JQogIGdncGxvdChhZXMoY19vYnNlcnZlLCBmX29ic2VydmUpKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrICAKICAgICNnZW9tX2FibGluZShpbnRlcmNlcHQgPSAzMiwgc2xvcGUgPSAxLjgsIGNvbG9yID0gImdyZXk0MCIpKwogICAgZ2VvbV9wb2ludCgpKwogICAgI3N0YXRfc21vb3RoKG1ldGhvZCA9IGxtKSsKICAgICN4bGltKC0xMCwgNDApKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgI3lsaW0oMCwgMTAwKSsKICAgIHlsYWIoIkZhcmVuaGVpdCIpKwogICAgY29vcmRfZml4ZWQoKSsKICAgIHRoZW1lX21pbmltYWwoKQoKYGBgCgoKSW4gdGhpcyBjYXNlLCB5b3UgbWlnaHQgd2FudCB0byBmaXQgYSAqKmxpbmVhciByZWdyZXNzaW9uKiouIEEgbGluZWFyIHJlZ3Jlc3Npb24gYXNzdW1lcyB0aGF0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0d28gdmFyaWFibGVzIGNhbiBiZSBjYXB0dXJlZCB1c2luZyAqc29tZSogbGluZSwgYW5kIGl0IHRyaWVzIHRvIGVzdGltYXRlIHRoZSAqSW50ZXJjZXB0KiBhbmQgKlNsb3BlKiBvZiB0aGlzIGFzc3VtZWQgbGluZS4KClRoZSB3YXkgaXQgZG9lcyB0aGlzIGlzIGJ5IHRyeWluZyB0byBmaW5kIHBhcmFtZXRlcnMgZm9yIGEgbGluZSB0aGF0IG1pbmltaXplIHRoZSAiZXJyb3IiIG9yIHRoZSAicmVzaWR1YWxzIiBiZXR3ZWVuIHRoZSBvYnNlcnZlZCBkYXRhLCBhbmQgdGhlIGxpbmUuIEZvciBleGFtcGxlLCBoZXJlIGFyZSBleGFtcGxlcyBvZiAqYmFkKiBsaW5lcy4gVGhlIGZpcnN0IGFzc3VtZXMgdGhhdCBhbGwgdGVtcGVyYXR1cmVzIENlbGNpdXMgYXJlIGJhc2ljYWxseSA1MCYjMTc2O0YuIFRoZSBvdGhlciBhc3N1bWVzIHRoYXQgYWxsIHRlbXBlcmF0dXJlcyBpbiBGYXJlbmhlaXQgYXJlIGJhc2ljYWxseSAzJFx0aW1lcyRDLgoKPGRpdiBzdHlsZSA9ICJmbG9hdDpsZWZ0O3dpZHRoID0gNDUlOyI+CmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QodGVtcF9kZiwgYWVzKGNfb2JzZXJ2ZSwgZl9vYnNlcnZlKSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSBjX29ic2VydmUsIHllbmQgPSA1MCkpKwogICAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NDAiKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBjb2xvciA9ICdyZWQnKSsKICAgICNzdGF0X3Ntb290aChtZXRob2QgPSAnbG0nLCBjb2xvciA9ICdyZWQnLCBzZSA9IEYpKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW5oZWl0IikrCiAgICB0aGVtZV9taW5pbWFsKCkrCiAgICBnZ3RpdGxlKCJGID0gNTAiKQoKYGBgCjwvZGl2Pgo8ZGl2IHN0eWxlID0gImZsb2F0OmxlZnQ7d2lkdGggPSA0NSU7Ij4KYGBge3IgZWNobyA9IEYsIHdpZHRoID0gM30KZ2dwbG90KHRlbXBfZGYsIGFlcyhjX29ic2VydmUsIGZfb2JzZXJ2ZSkpKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsgIAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ZW5kID0gY19vYnNlcnZlLCB5ZW5kID0gY19vYnNlcnZlICogMykpKwogICAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NDAiKSsKICAgIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMywgY29sb3IgPSAicmVkIikrCiAgICAjc3RhdF9zbW9vdGgobWV0aG9kID0gJ2xtJywgY29sb3IgPSAncmVkJywgc2UgPSBGKSsKICAgIHhsYWIoIkNlbGNpdXMiKSsKICAgIHlsYWIoIkZhcmVuaGVpdCIpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgiRiA9IDMqQyIpCgpgYGAKPC9kaXY+CgpIZXJlIGlzIGEgcGxvdCBvZiB0aGUgYmVzdC1maXR0aW5nIGxpbmUsIHRoYXQgaGFzIHRoZSBzbWFsbGVzdCBhdmVyYWdlIHJlc2lkdWFscy4KYGBge3IgZWNobyA9IEZ9CnRlbXBfbW9kIDwtIGxtKGZfb2JzZXJ2ZX5jX29ic2VydmUsIGRhdGEgPSB0ZW1wX2RmKQp0ZW1wX2RmJGZpdHRlZCA8LSBmaXR0ZWQodGVtcF9tb2QpCgpnZ3Bsb3QodGVtcF9kZiwgYWVzKGNfb2JzZXJ2ZSwgZl9vYnNlcnZlKSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSBjX29ic2VydmUsIHllbmQgPSBmaXR0ZWQpKSsKICAgIGdlb21fcG9pbnQoY29sb3IgPSAiZ3JleTQwIikrCiAgICBzdGF0X3Ntb290aChtZXRob2QgPSAnbG0nLCBjb2xvciA9ICdyZWQnLCBzZSA9IEYsIGZ1bGxyYW5nZSA9IFQpKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW5oZWl0IikrCiAgICB0aGVtZV9taW5pbWFsKCkKCiAgICAKYGBgCgpUaGVyZSBhcmUgYWN0dWFsbHkgbWFueSBkaWZmZXJlbnQgd2F5cyB0byBmaWd1cmUgb3V0IHdoYXQgdGhlIGJlc3QgbGluZSBpcyAocmVtZW1iZXJpbmcgdGhhdCBieSAibGluZSIgd2UgcmVhbGx5IG1lYW4gdGhlIHBhaXJpbmcgb2YgSW50ZXJjZXB0IGFuZCBTbG9wZSkuIApGb3IgZXhhbXBsZSwgb25lIHJlYWxseSBzaW1wbGlzdGljIGFwcHJvYWNoXltBY3R1YWxseSwgdGhpcyAic2ltcGxpc3RpYyBhcHByb2FjaCIgaXMgbW9yZSBsaWtlIHRoZSBzb3BoaXN0aWNhdGVkIGFwcHJvYWNoIHRoZXNlIGRheXMsIGJlY2F1c2UgdGhlcmUgYXJlIGNvbXBsaWNhdGVkIG1hdGhzIGJlaGluZCBtYWtpbmcgZ29vZCBndWVzc2VzIHdoaWNoIGFyZSBnaXZlbiBzZW1hbnRpY2FsbHkgb3BhcXVlIG5hbWVzIGxpa2UgIlNpbXVsYXRlZCBBbm5lYWxpbmciIGFuZCAiSGFtaWx0b25pYW4gTW9udGUgQ2FybG8iLl0gd291bGQgYmUganVzdCB0byBkcmF3IGEgYnVuY2ggb2YgZGlmZmVyZW50IGxpbmVzLCBhbmQgc2VlIHdoaWNoIG9uZSB3b3JrZWQgYmVzdC4KCgoKYGBge3IgZWNobyA9IEZ9CnRlbXBfY29lZiA8LSBjb2VmKHRlbXBfbW9kKQp0ZW1wX1NpZ21hIDwtIHZjb3YodGVtcF9tb2QpCgptb2RfZGYgPC0gZGF0YS5mcmFtZShjX29ic2VydmUgPSAtMTQ6NDEpCm1vZF9tYXRyaXggPC0gbW9kZWwubWF0cml4KH5jX29ic2VydmUsIGRhdGEgPSBtb2RfZGYpCgoKQmV0YSA8LSBNQVNTOjptdnJub3JtKDYsIHRlbXBfY29lZiwgdGVtcF9TaWdtYSAqIDUwKQphc190aWJibGUodChCZXRhICUqJSB0KG1vZF9tYXRyaXgpKSkgJT4lCiAgYmluZF9jb2xzKG1vZF9kZiwgLiklPiUKICBnYXRoZXIoa2V5LCB2YWx1ZSwgLWNfb2JzZXJ2ZSklPiUKICBnZ3Bsb3QoYWVzKGNfb2JzZXJ2ZSwgdmFsdWUpKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrICAKICAgIGdlb21fcG9pbnQoZGF0YSA9IHRlbXBfZGYsIAogICAgICAgICAgICAgICBhZXMoeSA9IGZfb2JzZXJ2ZSksIAogICAgICAgICAgICAgICBncm91cCA9IE5BLAogICAgICAgICAgICAgICBjb2xvciA9ICJncmV5ODAiKSsKICAgIGdlb21fbGluZShhZXMoZ3JvdXAgPSBrZXkpLCBjb2xvciA9ICJncmV5NDAiKSsKICAgIHN0YXRfc21vb3RoKGRhdGEgPSB0ZW1wX2RmLCAKICAgICAgICAgICAgICAgIGFlcyhjX29ic2VydmUsIGZfb2JzZXJ2ZSksIAogICAgICAgICAgICAgICAgY29sb3IgPSAncmVkJywKICAgICAgICAgICAgICAgIG1ldGhvZCA9IGxtLCAKICAgICAgICAgICAgICAgIHNlID0gRiwKICAgICAgICAgICAgICAgIGZ1bGxyYW5nZSA9IFQpKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW5oZWl0IikrICAKICAgIHRoZW1lX21pbmltYWwoKQoKYGBgCgpIb3dldmVyLCB0aGVyZSBoYXZlIGJlZW4gc29tZSBsb25nIGVzdGFibGlzaGVkIG1ldGhvZHMgZm9yICpzb2x2aW5nKiB0aGlzIHByb2JsZW0sIGF0IGlzLCBmb3IgZmluZGluZyB0aGUgb25lIGFuZCB0cnVseSBiZXN0IEludGVyY2VwdCBhbmQgU2xvcGUgZm9yIGEgZ2l2ZW4gc2V0IG9mIGRhdGEgcG9pbnRzLgoKPGRpdiBjbGFzcyA9ICJib3ggaWRpb20iPgo8c3BhbiBjbGFzcyA9ICdsYWJlbCc+SWRpb208L3NwYW4+CgpUaGlzIGlzbid0IFIgaWRpb20sIGJ1dCBzdGF0cyBpZGlvbS4gSGVyZSBhcmUgc29tZSB0cmFuc2xhdGlvbnMgZm9yIGhvdyBwZW9wbGUgZGVzY3JpYmUgc29sdmluZyB0aGlzIHByb2JsZW0uCgotICphbmFseXRpYyosICpjbG9zZWQgZm9ybSogPSAiV2Ugc29sdmVkIGl0IHdpdGggY29tcGxpY2F0ZWQgbWF0aC4iCi0gKml0ZXJhdGl2ZSosICpzdG9jaGFzdGljKiA9ICJXZSBtYWRlIGEgYnVuY2ggb2YgZ3Vlc3Nlcy4iCgo8L2Rpdj4KCgpGb3IgdGhlIHNha2Ugb2YgZmluaXNoaW5nIHRoZSBpbGx1c3RyYXRpb24sIGhlcmUgaXMgdGhlIHNvbHV0aW9uIHRoYXQgYSBsaW5lYXIgcmVncmVzc2lvbiBmb3VuZCBmb3IgdGhpcyBzYW1wbGUgZGF0YToKCmBgYHtyIGVjaG8gPSBGfQp0ZW1wX21vZApgYGAKClRoZSBtb2RlbCBoYXMgZXN0aW1hdGVkIHRoYXQgdGhlIEludGVyY2VwdCBpcyAkXGFwcHJveCQgYHIgcm91bmQoY29lZih0ZW1wX21vZClbMV0pYCAgYW5kIHRoZSBzbG9wZSBpcyAkXGFwcHJveCQgYHIgcm91bmQoY29lZih0ZW1wX21vZClbMl0sIGRpZ2l0cyA9IDEpYCAuIFRoYXQgaXMgdG8gc2F5LCBiYXNlZCBvbiBvdXIgInNhbXBsZSIsIGl0IHRoaW5rcyAwJiMxNzY7QyA9IGByIHJvdW5kKGNvZWYodGVtcF9tb2QpWzFdKWAmIzE3NjtGLCBhbmQgdGhhdCBldmVyeSAxJiMxNzY7QyBpbmNyZWFzZSBjb3JyZXNwb25kcyB0byBhIGByIHJvdW5kKGNvZWYodGVtcF9tb2QpWzJdLCBkaWdpdHMgPSAxKWAmIzE3NjtGIGluY3JlYXNlLgoKV2UgYXJlIGx1Y2t5IHRvIGtub3cgdGhhdCB0aGlzIGlzLCBzdHJpY3RseSBzcGVha2luZywgd3JvbmcsIGJ1dCB3ZSB3b24ndCB1c3VhbGx5LCBvciB0eXBpY2FsbHksIGJlIGFibGUgdG8gaW4gc3VjaCBhIHNpdHVhdGlvbi4gSG93ZXZlciwgdGhlIGVzdGltYXRlIG9mIGJvdGggdGhlIGludGVyY2VwdCBhbmQgc2xvcGUgaGF2ZSB0aGUgcmlnaHQgKnNpZ24qICh0aGF0IGlzLCBpdCBoYXNuJ3QgZ3Vlc3NlZCB0aGUgaW50ZXJjZXB0IGlzIC0xMCwgb3IgdGhlIHNsb3BlIGdvZXMgdGhlIG90aGVyIHdheSksIGFuZCB0aGV5J3JlIGp1c3QgYWJvdXQgdGhlIHJpZ2h0ICptYWduaXR1ZGUqICh0aGF0IGlzLCBpdCBoYXNuJ3QgZ3Vlc3NlZCB0aGF0IHRoZSBzbG9wZSBpcyBzb21ldGhpbmcgbGlrZSAxMCwgb3IgMTAwKS4KCk5vdywgbGV0J3MgY29uc2lkZXIgaG93IHRoZSBsaW5lYXIgbW9kZWwgaXMgZGVzY3JpYmluZyB0aGUgdmFsdWUgb2YgdGhpcyBoaWdobGlnaHRlZCBkb3QuCmBgYHtyIGVjaG8gPSBGfQpvbmVfZG90IDwtIHRlbXBfZGYgJT4lIAogICAgICAgICAgICAgICAgc2FtcGxlX24oMSkKCgpnZ3Bsb3QodGVtcF9kZiwgYWVzKGNfb2JzZXJ2ZSwgZl9vYnNlcnZlKSkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsgIAogICAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NDAiKSsKICAgIHN0YXRfc21vb3RoKG1ldGhvZCA9ICdsbScsIHNlID0gRiwgY29sb3IgPSAnYmxhY2snLCBzaXplID0gMC41KSsKICAgIGdlb21fcG9pbnQoZGF0YSA9IG9uZV9kb3QsIGNvbG9yID0gJ3JlZCcsIHNpemUgPSAzKSsKICAgIHhsYWIoIkNlbGNpdXMiKSsKICAgIHlsYWIoIkZhcmVudGhlaXQiKSsgIAogICAgdGhlbWVfbWluaW1hbCgpCmBgYAoKRmlyc3QsIHlvdSB0YWtlIGl0J3MgdmFsdWUgaW4gQ2VsY2l1cywgYW5kIDxzcGFuIHN0eWxlID0gImNvbG9yOiMyMTZENjU7Zm9udC13ZWlnaHQ6Ym9sZDsiPm11bHRpcGx5IGl0IGJ5IGByIGNvZWYodGVtcF9tb2QpWzJdYDwvc3Bhbj4gKHdoaWNoIGlzIGByIHJvdW5kKG9uZV9kb3QkY19vYnNlcnZlWzFdICogY29lZih0ZW1wX21vZClbMl0sIGRpZ2l0cyA9IDIpYCkKCmBgYHtyIGVjaG8gPSBGfQpvbmVfZG90JG11bHQgPC0gb25lX2RvdCRjX29ic2VydmUgKiBjb2VmKHRlbXBfbW9kKVsyXQpnZ3Bsb3QodGVtcF9kZiwgYWVzKGNfb2JzZXJ2ZSwgZl9vYnNlcnZlKSkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgID0gMikrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsgIAogICAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NDAiKSsKICAgIHN0YXRfc21vb3RoKG1ldGhvZCA9ICdsbScsIHNlID0gRiwgY29sb3IgPSAnYmxhY2snLCBzaXplID0gMC41KSsKICAgIGdlb21fcG9pbnQoZGF0YSA9IG9uZV9kb3QsIGNvbG9yID0gJ3JlZCcsIHNpemUgPSAzKSsKICAgIGdlb21fc2VnbWVudChkYXRhID0gb25lX2RvdCwgCiAgICAgICAgICAgICAgICAgYWVzKHhlbmQgPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICB4ID0gY19vYnNlcnZlLTAuNSwKICAgICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBtdWx0KSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMjE2RDY1IiwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCkpKwogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW50aGVpdCIpKyAgCiAgICB0aGVtZV9taW5pbWFsKCkKYGBgCgoKVGhlbiw8c3BhbiBzdHlsZSA9ICJjb2xvcjojQjA4NTM0O2ZvbnQtd2VpZ2h0OmJvbGQ7Ij55b3UgYWRkIGByIGNvZWYodGVtcF9tb2QpWzFdYCB0byBpdDwvc3Bhbj4gKHdoaWNoIGlzIGByIHJvdW5kKChvbmVfZG90JGNfb2JzZXJ2ZVsxXSAqIGNvZWYodGVtcF9tb2QpWzJdKSArIGNvZWYodGVtcF9tb2QpWzFdLCBkaWdpdHMgPSAyKWApCgpgYGB7ciBlY2hvID0gRn0Kb25lX2RvdCRhZGQgPC0gb25lX2RvdCRtdWx0ICsgY29lZih0ZW1wX21vZClbMV0KCmdncGxvdCh0ZW1wX2RmLCBhZXMoY19vYnNlcnZlLCBmX29ic2VydmUpKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKyAgCiAgICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXk0MCIpKwogICAgc3RhdF9zbW9vdGgobWV0aG9kID0gJ2xtJywgc2UgPSBGLCBjb2xvciA9ICdibGFjaycsIHNpemUgPSAwLjUpKwogICAgZ2VvbV9wb2ludChkYXRhID0gb25lX2RvdCwgY29sb3IgPSAncmVkJywgc2l6ZSA9IDMpKwogICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICBhZXMoeGVuZCA9IGNfb2JzZXJ2ZS0wLjUsCiAgICAgICAgICAgICAgICAgICAgIHggPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICB5ID0gMCwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IG11bHQpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gIiMyMTZENjUiLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICAgYWVzKHggPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IGNfb2JzZXJ2ZSArIDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHkgPSBtdWx0LAogICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IG11bHQpLAogICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmV5MjAiKSsKICAgICBnZW9tX3NlZ21lbnQoZGF0YSA9IG9uZV9kb3QsIAogICAgICAgICAgICAgICAgIGFlcyh4ZW5kID0gY19vYnNlcnZlICsgMC41LAogICAgICAgICAgICAgICAgICAgICB4ID0gY19vYnNlcnZlKzAuNSwKICAgICAgICAgICAgICAgICAgICAgeSA9IG11bHQsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBhZGQpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gIiNCMDg1MzQiLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICB4bGFiKCJDZWxjaXVzIikrCiAgICB5bGFiKCJGYXJlbnRoZWl0IikrICAKICAgIHRoZW1lX21pbmltYWwoKQpgYGAKClRoZW4sIHlvdSA8c3BhbiBzdHlsZSA9ICJjb2xvcjojQUMzMzNDO2ZvbnQtd2VpZ2h0OmJvbGQ7Ij5hZGQgdGhlIHJlc2lkdWFsIGVycm9yPC9zcGFuPiB0byBnaXZlIHVzIHRoZSBvYnNlcnZlZCBkYXRhIHBvaW50LgoKYGBge3IgZWNobyA9IEZ9CmdncGxvdCh0ZW1wX2RmLCBhZXMoY19vYnNlcnZlLCBmX29ic2VydmUpKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSAgPSAyKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlICA9IDIpKyAgCiAgICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXk0MCIpKwogICAgc3RhdF9zbW9vdGgobWV0aG9kID0gJ2xtJywgc2UgPSBGLCBjb2xvciA9ICdibGFjaycsIHNpemUgPSAwLjUpKwogICAgZ2VvbV9wb2ludChkYXRhID0gb25lX2RvdCwgY29sb3IgPSAncmVkJywgc2l6ZSA9IDMpKwogICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICBhZXMoeGVuZCA9IGNfb2JzZXJ2ZS0wLjUsCiAgICAgICAgICAgICAgICAgICAgIHggPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICB5ID0gMCwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IG11bHQpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gIiMyMTZENjUiLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICAgYWVzKHggPSBjX29ic2VydmUtMC41LAogICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IGNfb2JzZXJ2ZSArIDAuNSwKICAgICAgICAgICAgICAgICAgICAgIHkgPSBtdWx0LAogICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IG11bHQpLAogICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmV5MjAiKSsKICAgICBnZW9tX3NlZ21lbnQoZGF0YSA9IG9uZV9kb3QsIAogICAgICAgICAgICAgICAgIGFlcyh4ZW5kID0gY19vYnNlcnZlICsgMC41LAogICAgICAgICAgICAgICAgICAgICB4ID0gY19vYnNlcnZlKzAuNSwKICAgICAgICAgICAgICAgICAgICAgeSA9IG11bHQsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBhZGQpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gIiNCMDg1MzQiLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICAgYWVzKHggPSBjX29ic2VydmUsCiAgICAgICAgICAgICAgICAgICAgICB4ZW5kID0gY19vYnNlcnZlICsgMC41LAogICAgICAgICAgICAgICAgICAgICAgeSA9IGFkZCwKICAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBhZGQpLAogICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmV5MjAiKSsgCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBvbmVfZG90LCAKICAgICAgICAgICAgICAgICBhZXMoeGVuZCA9IGNfb2JzZXJ2ZSwKICAgICAgICAgICAgICAgICAgICAgeCA9IGNfb2JzZXJ2ZSwKICAgICAgICAgICAgICAgICAgICAgeSA9IGFkZCwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGZfb2JzZXJ2ZSksCiAgICAgICAgICAgICAgICAgY29sb3IgPSAiI0FDMzMzQyIsCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsgIAogICAgeGxhYigiQ2VsY2l1cyIpKwogICAgeWxhYigiRmFyZW50aGVpdCIpKyAgCiAgICB0aGVtZV9taW5pbWFsKCkKYGBgCgpUaGUgZ2VuZXJpYyBmb3JtdWxhIGZvciBmaW5kaW5nIHRoZSB2YWx1ZSBmb3IgKmFueSogZGF0YSBwb2ludCBpcwoKJCQKRl9pID0gYHIgcm91bmQoY29lZih0ZW1wX21vZClbMV0sIGRpZ2l0cyA9IDEpYCArIChgciByb3VuZChjb2VmKHRlbXBfbW9kKVsyXSwgZGlnaXRzID0gMSlgXHRpbWVzIENfaSkgKyBcZXBzaWxvbl9pLgokJApJbiB0aGlzIGZvcm11bGEgdGhlICRpJCBpcyBjb252ZW50aW9uIGZvciByZWZlcnJpbmcgdG8gc29tZSBnZW5lcmljLCAkaV57dGh9JCBkYXRhIHBvaW50IGFuZCAkXGVwc2lsb24kIGlzIGNvbnZlbnRpb25hbCBmb3IgcmVmZXJyaW5nIHRvIHRoZSByZXNpZHVhbCBlcnJvcnMuCgpTb21lIGFkZGl0aW9uYWwgY29udmVudGlvbnM6CgotIFJlZmVycmluZyB0byB0aGUgb3V0Y29tZSB2YXJpYWJsZSBhcyAkeSQuCi0gUmVmZXJyaW5nIHRvIHRoZSBwcmVkaWN0b3JzIGFzICR4JC4KLSBSZWZlcnJpbmcgdG8gdGhlIHJlbWFpbmluZyBwYXJhbWV0ZXJzIGFzICRcYmV0YSQuCgpTbyB5b3UgbWF5IHNvbWV0aW1lcyBzZWUgcGVvcGxlIHJlZmVycmluZyB0byAkXGJldGFfMCQsIG9yIHRoZSAiYmV0YXMiIGluIGEgbW9kZWwuIFRoZSBmdWxseSBnZW5lcmljIGZvcm11bGEgZm9yIGxpbmVhciByZWdyZXNzaW9uIGlzIHNvbWV0aW1lcyBnaXZlbiBhcwoKCiQkCnlfaSA9IFxiZXRhXzAgKyBcYmV0YSB4X2kgKyBcZXBzaWxvbl9pCiQkCgoKPGRpdiBjbGFzcyA9ICJib3ggaWRpb20iPgo8c3BhbiBjbGFzcyA9ICdsYWJlbCc+SWRpb208L3NwYW4+CgotIFdlIGNhbGwgdGhlICpJbnRlcmNlcHQqIGFuZCAqU2xvcGVzKiB0aGUgKipwYXJhbWV0ZXJzKiogb3IgKipjb2VmZmljaWVudHMqKiBvZiB0aGUgbW9kZWwuCi0gRm9yIGV2ZXJ5IGRhdGEgcG9pbnQsIHRoZSB2YWx1ZSB5b3UgZ2V0IGJ5IG9ubHkgdXNpbmcgdGhlIHNsb3BlcyBhbmQgaW50ZXJjZXB0cyBhcmUgY2FsbGVkIHRoZSAqKmZpdHRlZCB2YWx1ZXMqKiwgYW5kIHRoZXkgYWxsIGxpZSBhbG9uZyB0aGUgbGluZXMgeW91IGRyYXcuCi0gQWxtb3N0IGV2ZXJ5IGRhdGEgcG9pbnQncyBhY3R1YWwgdmFsdWUgaXMgZGlmZmVyZW50IGZyb20gaXRzIGZpdHRlZCB2YWx1ZSwgYW5kIHRoZXNlIGRpZmZlcmVuY2VzIGFyZSBjYWxsZWQgdGhlICoqcmVzaWR1YWxzKiouCgo8L2Rpdj4KCiMjIFVuZGVyc3RhbmRpbmcgY2F0ZWdvcmljYWwgcHJlZGljdG9ycwoKQ2F0ZWdvcmljYWwgdmFyaWFibGVzIGFyZSBuZWNlc3NhcmlsbHkgdHJlYXRlZCBkaWZmZXJlbnRseSBpbiByZWdyZXNzaW9uIG1vZGVscy4KVGhpcyBpcyBiZWNhdXNlIHdoaWxlIHlvdSBjYW4gbXVsdGlwbHkgbnVtZXJpYyBwcmVkaWN0b3JzIHRvZ2V0aGVyLCB5b3UgY2FuJ3QgbXVsdGlwbHkgNSAkXHRpbWVzJCAiZXhwZXJpbWVudGFsIGNvbmRpdGlvbiIuCgpUbyBpbGx1c3RyYXRlIGhvdyBjYXRlZ29yaWNhbCBwcmVkaWN0b3JzIHdvcmsgaW4gYSBsaW5lYXIgcmVncmVzc2lvbiwgd2UnbGwgdXNlIHNvbWUgZXhhbXBsZSB3ZWF0aGVyIGRhdGEuCkkgcHVsbGVkIHRoaXMgZGF0YSBvZiB0aGUgZGFpbHkgdGVtcGVyYXR1cmUgZnJvbSBbdGhlIFVuaXZlcnNpdHkgb2YgRWRpbmJ1cmdoIEdlb3NjaWVuY2VzIERlcGFydG1lbnQgd2VhdGhlciBzdGF0aW9uXShodHRwczovL3d3dy5lZC5hYy51ay9nZW9zY2llbmNlcy93ZWF0aGVyLXN0YXRpb24vd2VhdGhlci1zdGF0aW9uLWRhdGEpLgoKCmBgYHtyIGVjaG8gPUYsIGV2YWwgPSBGfQp3ZWF0aGVycyA8LSBwYXN0ZSgiaHR0cHM6Ly93d3cuZ2Vvcy5lZC5hYy51ay9+d2VhdGhlci9qY21iX3dzL0pDTUJfIiwgc2VxKDIwMDcsIDIwMTUpLCAiLmNzdiIsIHNlcCA9ICIiKQp3ZWF0aGVyX2xpc3QgPC0gbWFwKHdlYXRoZXJzLCByZWFkLmNzdikKd2VhdGhlcl9kZiA8LSBiaW5kX3Jvd3Mod2VhdGhlcl9saXN0KQpgYGAKYGBge3IgZWNobyA9IEZ9CndlYXRoZXJfZGYgPC0gcmVhZF9jc3YoIi4uL2RhdGEvZWRpbl93ZWF0aGVyLmNzdiIpCmBgYAoKCmBgYHtyIGVjaG8gPSBGfQpsaWJyYXJ5KGx1YnJpZGF0ZSkKd2VhdGhlcl9kZiAlPiUKICBmaWx0ZXIoc3VyZmFjZS50ZW1wZXJhdHVyZS4uQy4gPiAtMjAsCiAgICAgICAgIHN1cmZhY2UudGVtcGVyYXR1cmUuLkMuIDwgNDApJT4lCiAgbXV0YXRlKGRhdGUudGltZSA9IHltZF9obShkYXRlLnRpbWUpLAogICAgICAgICBkYXRlID0gYXMuRGF0ZShkYXRlLnRpbWUpKSAlPiUKICBncm91cF9ieShkYXRlKSU+JQogIHN1bW1hcmlzZSh0ZW1wID0gbWVhbihzdXJmYWNlLnRlbXBlcmF0dXJlLi5DLikpJT4lCiAgbXV0YXRlKG1vbnRoID0gbW9udGgoZGF0ZSwgbGFiZWwgPSBUKSwKICAgICAgICAgc2Vhc29uID0gcmVjb2RlKG1vbnRoLAogICAgICAgICAgICAgICAgICAgICAgICAgSmFuID0gIldpbnRlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICBGZWIgPSAiV2ludGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgIE1hciA9ICJTcHJpbmciLAogICAgICAgICAgICAgICAgICAgICAgICAgQXByID0gIlNwcmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICBNYXkgPSAiU3ByaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgIEp1biA9ICJTdW1tZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgSnVsID0gIlN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICBBdWcgPSAiU3VtbWVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgIFNlcCA9ICJBdXR1bW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgT2N0ID0gIkF1dHVtbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICBOb3YgPSAiQXV0dW1uIiwKICAgICAgICAgICAgICAgICAgICAgICAgIERlYyA9ICJXaW50ZXIiKSwKICAgICAgICAgc2Vhc29uID0gZmFjdG9yKHNlYXNvbiwgb3JkZXJlZCA9IEYpLAogICAgICAgICBkYXkgPSB5ZGF5KGRhdGUpLAogICAgICAgICB5ZWFyID0geWVhcihkYXRlKSkgLT4gdGVtcHMKYGBgCgpgYGB7ciBlY2hvID0gRn0gCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoc2NhbGVzKQp0ZW1wcyAlPiUgCiAgZmlsdGVyKGlzLmZpbml0ZSh0ZW1wKSkgJT4lCiAgZ3JvdXBfYnkobW9udGgsIHllYXIpJT4lCiAgbXV0YXRlKGV4dHJlbWEgPSAibm8iLAogICAgICAgICBleHRyZW1hID0gaW5zZXQoZXh0cmVtYSwgd2hpY2gubWF4KHRlbXApLCAiaGkiKSwKICAgICAgICAgZXh0cmVtYSA9IGluc2V0KGV4dHJlbWEsIHdoaWNoLm1pbih0ZW1wKSwgImxvIikpLT50ZW1wcwoKZ2dwbG90KHRlbXBzLCBhZXMoZGF0ZSwgdGVtcCkpKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSBtdXRlZCgiYmx1ZSIpKSsKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gZXh0cmVtYSkpKwogICAgc2NhbGVfY29sb3JfbWFudWFsKGxpbWl0cyA9IGMoImhpIiwgIm5vIiwibG8iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygicmVkIiwgImdyZXk0MCIsICJibHVlIiksCiAgICAgICAgICAgICAgICAgICAgICAgZ3VpZGUgPSAibm9uZSIpKwogICAgeWxhYigiZGFpbHkgYXZlcmFnZSB0ZW1wdXJhdHVyZSIpKwogICAgdGhlbWVfbWluaW1hbCgpCmBgYAoKSW4gb3JkZXIgdG8gZm9jdXMgb24gYSBjYXRlZ29yaWNhbCBlZmZlY3QsIEkndmUgcmVjb2RlZCB0aGUgZGF0ZSB2YXJpYWJsZSBpbnRvICJzZWFzb25zIiBsaWtlIHNvOgoKPGRpdiBzdHlsZSA9ICJ3aWR0aDo1MCU7bWFyZ2luOmF1dG87Ij4KCmBgYHtyIHJlc3VsdHMgPSAnYXNpcycsIGVjaG8gPSBGfQpsaWJyYXJ5KGtuaXRyKQp0ZW1wcyAlPiUgCiAgdW5ncm91cCgpJT4lCiAgY291bnQobW9udGgsIHNlYXNvbikgJT4lCiAgc2VsZWN0KC1uKSU+JQogIGthYmxlKCkKYGBgCjwvZGl2PgoKV2UnbGwgZm9jdXMgb24ganVzdCB0aGUgc3Vic2V0IG9mIDIwMTAgYW5kIDIwMTEsIGJlY2F1c2UgMjAxMCB3YXMgYSBub3RhYmx5IGNvbGQgd2ludGVyLiAKSGVyZSdzIGFsbCBvZiB0aGUgZGF0YSBmb3IgdGhlIGZvdXIgc2Vhc29ucyBmcm9tIDIwMTAgYW5kIDIwMTEuCmBgYHtyIGVjaG8gPSBGfQp0ZW1wcyAlPiUKICBmaWx0ZXIoeWVhciAlaW4lIGMoMjAxMCwgMjAxMSkpIC0+IHRlbXBzX2NvbXAKdGVtcHNfY29tcCAlPiUKZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjIpKSsKICAgIHRoZW1lX21pbmltYWwoKQpgYGAKCldpbnRlciBpcyB0aGUgInJlZmVyZW5jZSBsZXZlbCIsIGZvciB0aGUgc2Vhc29uJ3MgZmFjdG9yLCB3aGljaCB5b3UgY2FuIHNlZSBpZiB5b3UgdXNlIGBsZXZlbHMoKWAuCgpgYGB7cn0KbGV2ZWxzKHRlbXBzX2NvbXAkc2Vhc29uKQpgYGAKCldoZW4gdXNpbmcgdHJlYXRtZW50IGNvbnRyYXN0cywgdGhlIGZpcnN0IGxldmVsIGlzIGFsd2F5cyB0cmVhdGVkIGFzIHRoZSByZWZlcmVuY2UgbGV2ZWwuCgpJZiB3ZSBmaXQgYSBsaW5lYXIgbW9kZWwgdG8gdGhpcyBkYXRhLCB3ZSBnZXQgdGhlIGZvbGxvd2luZyBzb2x1dGlvbjoKYGBge3IgZWNobyA9IEZ9CnNlYXNvbl9tb2RlbCA8LSBsbSh0ZW1wIH4gc2Vhc29uLCAKICAgICAgICAgICAgICAgICAgIGRhdGEgPSB0ZW1wc19jb21wKQpzdW1tYXJ5KHNlYXNvbl9tb2RlbCkKYGBgCgpXZSd2ZSBnb3QgYSBidW5jaCBvZiBwYXJhbWV0ZXIgZXN0aW1hdGVzIHVuZGVyICJFc3RpbWF0ZSIgYW5kIGEgYnVuY2ggb2Ygc2lnbmlmaWNhbnQgcC12YWx1ZXMuCkJ1dCB3aGF0IGRvZXMgaXQgbWVhbiB0byBzYXkgIlRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9mIFNwcmluZyI/IApBbmQgY2FuIHdlIHNheSBhbnRoaW5nIGFib3V0LCBzYXksIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gU3ByaW5nIGFuZCBBdXR1bW4/CkFwcHJvYWNoIHJlc3VsdHMgdGhhdCBsb29rIGxpa2UgdGhpcyBleGFjdGx5IGxpa2UgeW91IHdvdWxkIGEgcmVncmVzc2lvbiB3aXRoIGNvbnRpbnVvdXMgcHJlZGljdG9yczogdHJ5IHRvIGRyYXcgdGhlIGdyYXBoIGl0IGlzIGEgcmVjaXBlIGZvci4KCldlIHN0YXJ0IHdpdGggdGhlICJJbnRlcmNlcHQiLiAKV2l0aCBjb250aW51b3VzIHByZWRpY3RvcnMsIHRoZSAiaW50ZXJjZXB0IiBpcyB0aGUgeSB2YWx1ZSB3aGVyZSB0aGUgbGluZSBjcm9zc2VzIDAgb24gdGhlIHgtYXhpcyAoYS5rLmEuIHRoZSBwcmVkaWN0ZWQgdmFsdWUgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUgd2hlbiB0aGUgcHJlZGljdG9yIHZhcmlhYmxlIGlzIDApLiAKV2l0aCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIHRoZXJlIGFyZSBubyBsaW5lcyB0byBkcmF3IHRvIGRlc2NyaWJlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBvdXRjb21lIGFuZCBwcmVkaWN0b3IsIHNvIGNhbGxpbmcgaXQgYW4gaW50ZXJjZXB0IGlzIG1vcmUgb2YgYSBtZXRhcGhvcmljYWwgaG9sZG92ZXIgb2YgdGhlIGNvbnRpbnVvdXMgY2FzZS4gCgpVbmRlcnN0YW5kIHRoZSAiSW50ZXJjZXB0IiBmb3IgY2F0ZWdvcmljYWwgcHJlZGljdG9ycyB0byBiZSAqKnRoZSBwcmVkaWN0ZWQgYXZlcmFnZSBvZiB0aGUgcmV2ZXJlbmNlIGxldmVsKiouCkZvciB0aGUgc2Vhc29ucyBtb2RlbCwgdGhlIGludGVyY2VwdCBpcyBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMV0sIGRpZ2l0cyA9IDIpYCwgbWVhbmluZyB0aGUgZXN0aW1hdGVkIGF2ZXJhZ2Ugd2ludGVyIHRlbXBlcmF0dXJlIGluIEVkaW5idXJnaCBpcyBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMV0sIGRpZ2l0cyA9IDIpYAoKCmBgYHtyIGVjaG8gPSBGfQp0ZW1wc19jb21wICU+JQogIGdyb3VwX2J5KHNlYXNvbiklPiUKICBzdW1tYXJpc2UodGVtcCA9IG1lYW4odGVtcCkpLT50ZW1wX2NvbXBfbWVhbnMKCnRlbXBfY29tcF92ZWMgPC0gdGVtcF9jb21wX21lYW5zJHRlbXAKbmFtZXModGVtcF9jb21wX3ZlYykgPC0gdGVtcF9jb21wX21lYW5zJHNlYXNvbgp0ZW1wX2NvZWYgPC0gY29lZihzZWFzb25fbW9kZWwpCm5hbWVzKHRlbXBfY29lZikgPC0gdGVtcF9jb21wX21lYW5zJHNlYXNvbgp0ZW1wX3JhbmdlIDwtIHJhbmdlKHRlbXBzX2NvbXAkdGVtcCkKCmBgYAoKCmBgYHtyIGVjaG89IEZ9CnRlbXBfY29tcF9tZWFucyU+JQogIGZpbHRlcihzZWFzb24gPT0gIldpbnRlciIpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJXaW50ZXIiLCB5PTAsIHllbmQgPSB0ZW1wKSwgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAxLjUsIHkgPSAxLjUsIGxhYmVsID0gcGFzdGUwKCJpbnRlcmNlcHQ9Iixyb3VuZCh0ZW1wLCBkaWdpdHMgPSAxKSkpKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAiV2ludGVyIiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcF9jb21wX3ZlY1siV2ludGVyIl0rMSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcm91bmQodGVtcF9jb21wX3ZlY1siV2ludGVyIl0sIGRpZ2l0cyA9IDEpKSkrICAKICAgIHhsaW0oIldpbnRlciIsICJTcHJpbmciLCAiU3VtbWVyIiwgIkF1dHVtbiIpKwogICAgeWxpbSh0ZW1wX3JhbmdlWzFdLCB0ZW1wX3JhbmdlWzJdKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpOZXh0LCB3ZSBtb3ZlIHRvIHRoZSB0aGUgYFNwcmluZ2AgZWZmZWN0LgpNb2RlbCBlc3RpbWF0ZXMgYSBTcHJpbmcgZWZmZWN0IG9mIGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVsyXSwgZGlnaXRzID0gMilgLgpUaGlzIGlzICpub3QqIHRoZSBlc3RpbWF0ZWQgdGVtcGVyYXR1cmUgb2YgRWRpbmJ1cmdoIGluIHNwcmluZy4gVGhpcyBpcyAqKmhvdyBkaWZmZXJlbnQgdGhlIFNwcmluZyB0ZW1wZXJhdHVyZSBpcyBmcm9tIHRoZSBXaW50ZXIgdGVtcGVyYXR1cmUqKi4gCk1lYW5pbmcgdG8gZ2V0IHRoZSBlc3RpbWF0ZWQgU3ByaW5nIHRlbXBlcmF0dXJlIGZyb20gdGhlIG1vZGVsIHdlIG5lZWQgdG8gYWRkIHRoZSBTcHJpbmcgZWZmZWN0IHRvIHRoZSBpbnRlcmNlcHQgKGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVsxXSwgZGlnaXRzID0gMilgICsgYHIgcm91bmQoY29lZihzZWFzb25fbW9kZWwpWzJdLCBkaWdpdHMgPSAyKWAgPSBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMl0sIGRpZ2l0cyA9IDIpICtyb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMV0sIGRpZ2l0cyA9IDIpIGApCgoKYGBge3IgZWNobyA9IEZ9CnRlbXBfY29tcF9tZWFucyU+JQogIGZpbHRlcihzZWFzb24gPT0gIldpbnRlciIpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fcG9pbnQoZGF0YSA9IHRlbXBfY29tcF9tZWFucyAlPiUgZmlsdGVyKHNlYXNvbiA9PSAiU3ByaW5nIikpKwogICAgZ2VvbV9zdGVwKGRhdGE9IHRlbXBfY29tcF9tZWFucyAlPiUgZmlsdGVyKHNlYXNvbiAlaW4lIGMoIldpbnRlciIsICJTcHJpbmciKSksIAogICAgICAgICAgICAgIGFlcyhncm91cCA9IDEpKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJXaW50ZXIiLCB5PTAsIHllbmQgPSB0ZW1wKSwgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJTcHJpbmciLCAKICAgICAgICAgICAgICAgICAgICAgeCA9ICJTcHJpbmciLAogICAgICAgICAgICAgICAgICAgICB5ID0gdGVtcF9jb21wX3ZlY1siV2ludGVyIl0sCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSB0ZW1wX2NvbXBfdmVjWyJTcHJpbmciXSksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAiV2ludGVyIiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcF9jb21wX3ZlY1siV2ludGVyIl0rMSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcm91bmQodGVtcF9jb21wX3ZlY1siV2ludGVyIl0sIGRpZ2l0cyA9IDEpKSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAiU3ByaW5nIiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcF9jb21wX3ZlY1siU3ByaW5nIl0rMSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcm91bmQodGVtcF9jb21wX3ZlY1siU3ByaW5nIl0sIGRpZ2l0cyA9IDEpKSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAxLjQsIHkgPSAxLjUsIGxhYmVsID0gcGFzdGUwKCJpbnRlcmNlcHQ9Iixyb3VuZCh0ZW1wLCBkaWdpdHMgPSAxKSkpKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAyLjQsIHkgPSA1LCBsYWJlbCA9IHBhc3RlMCgic3ByaW5nPSsiLHJvdW5kKHRlbXBfY29lZlsiU3ByaW5nIl0sIGRpZ2l0cyA9IDEpKSkpKwogICAgeGxpbSgiV2ludGVyIiwgIlNwcmluZyIsICJTdW1tZXIiLCAiQXV0dW1uIikrCiAgICB5bGltKHRlbXBfcmFuZ2VbMV0sIHRlbXBfcmFuZ2VbMl0pKwogICAgdGhlbWVfYncoKQpgYGAKCk5leHQgdXAgaXMgdGhlIFN1bW1lciBlZmZlY3QsIHdoaWNoIHRoZSBtb2RlbCBlc3RpbWF0ZXMgaXMgIGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVszXSwgZGlnaXRzID0gMilgLiAKQWdhaW4sIHRoaXMgaXMgKm5vdCogdGhlIGVzdGltYXRlZCB0ZW1wZXJhdHVyZSBpbiB0aGUgc3VtbWVyLiAKVGhpcyBpcyAqaG93IGRpZmZlcmVudCBTdW1tZXIgaXMgZXN0aW1hdGVkIHRvIGJlIGZyb20gdGhlIEludGVyY2VwdCAoV2ludGVyKSouIApUbyBnZXQgdGhlIGVzdGltYXRlZCBTdW1tZXIgdGVtcGVyYXR1cmUgZnJvbSB0aGUgbW9kZWwgd2UgbmVlZCB0byBhZGQgdGhlIFN1bW1lciBlZmZlY3QgdG8gdGhlIGludGVyY2VwdCAoYHIgcm91bmQoY29lZihzZWFzb25fbW9kZWwpWzFdLCBkaWdpdHMgPSAyKWAgKyBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbM10sIGRpZ2l0cyA9IDIpYCA9IGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVszXSwgZGlnaXRzID0gMikgK3JvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVsxXSwgZGlnaXRzID0gMikgYCkuCgoKCgpgYGB7ciBlY2hvID0gRn0KdGVtcF9jb21wX21lYW5zJT4lCiAgZmlsdGVyKHNlYXNvbiAlaW4lIGMoIldpbnRlciIsICJTcHJpbmciLCAiU3VtbWVyIikpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fc3RlcChkYXRhPSB0ZW1wX2NvbXBfbWVhbnMgJT4lIGZpbHRlcihzZWFzb24gJWluJSBjKCJXaW50ZXIiLCAiU3VtbWVyIikpLCAKICAgICAgICAgICAgICBhZXMoZ3JvdXAgPSAxKSkrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSAiV2ludGVyIiwgeCA9ICJXaW50ZXIiLCB5ID0gMCwgeWVuZCA9IHRlbXBfY29tcF92ZWNbIldpbnRlciJdKSwgCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJTdW1tZXIiLCB4ID0gIlN1bW1lciIsIHkgPSB0ZW1wX2NvbXBfdmVjWyJXaW50ZXIiXSwgeWVuZCA9IHRlbXBfY29tcF92ZWNbIlN1bW1lciJdKSwgCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsgIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IHNlYXNvbiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcCArIDEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHJvdW5kKHRlbXAsIGRpZ2l0cyA9IDEpKSkrCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMS40LCB5ID0gMS41LCBsYWJlbCA9IHBhc3RlMCgiaW50ZXJjZXB0PSIscm91bmQodGVtcF9jb21wX3ZlY1siV2ludGVyIl0sIGRpZ2l0cyA9IDEpKSkpKwogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDMuNCwgeSA9IDEwLCBsYWJlbCA9IHBhc3RlMCgic3VtbWVyPSsiLHJvdW5kKHRlbXBfY29lZlsiU3VtbWVyIl0sIGRpZ2l0cyA9IDEpKSkpKwogICAgeGxpbSgiV2ludGVyIiwgIlNwcmluZyIsICJTdW1tZXIiLCAiQXV0dW1uIikrCiAgICB5bGltKHRlbXBfcmFuZ2VbMV0sIHRlbXBfcmFuZ2VbMl0pKwogICAgdGhlbWVfYncoKQpgYGAKCkFuZCwgd2hhdCBzaG91bGQgc2VlbSBmYW1pbGlhciBieSBub3csIHRoZSBlZmZlY3Qgb2YgQXV0dW1uIGlzIGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVs0XSwgZGlnaXRzID0gMilgLCBtZWFuaW5nIEF1dHVtbiBpcyBgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbNF0sIGRpZ2l0cyA9IDIpYCBkZWdyZWVzIHdhcm1lciB0aGFuIFdpbnRlciwgbWVhbmluZyB0aGUgZXN0aW1hdGVkIGF2ZXJhZ2UgdGVtcGVyYXR1cmUgaW4gQXV0dW1uIGlzIChgciByb3VuZChjb2VmKHNlYXNvbl9tb2RlbClbMV0sIGRpZ2l0cyA9IDIpYCArIGByIHJvdW5kKGNvZWYoc2Vhc29uX21vZGVsKVs0XSwgZGlnaXRzID0gMilgID0gYHIgcm91bmQoY29lZihzZWFzb25fbW9kZWwpWzRdLCBkaWdpdHMgPSAyKSArcm91bmQoY29lZihzZWFzb25fbW9kZWwpWzFdLCBkaWdpdHMgPSAyKSBgKS4KCgoKCmBgYHtyIGVjaG8gPSBGfQp0ZW1wX2NvbXBfbWVhbnMlPiUKICBmaWx0ZXIoc2Vhc29uICVpbiUgYygiV2ludGVyIiwgIlNwcmluZyIsICJTdW1tZXIiLCAiQXV0dW1uIikpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fcG9pbnQoKSsKICAgIGdlb21fc3RlcChkYXRhPSB0ZW1wX2NvbXBfbWVhbnMgJT4lIGZpbHRlcihzZWFzb24gJWluJSBjKCJXaW50ZXIiLCAiQXV0dW1uIikpLCAKICAgICAgICAgICAgICBhZXMoZ3JvdXAgPSAxKSkrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSAiV2ludGVyIiwgeCA9ICJXaW50ZXIiLCB5ID0gMCwgeWVuZCA9IHRlbXBfY29tcF92ZWNbIldpbnRlciJdKSwgCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsKICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9ICJBdXR1bW4iLCB4ID0gIkF1dHVtbiIsIHkgPSB0ZW1wX2NvbXBfdmVjWyJXaW50ZXIiXSwgeWVuZCA9IHRlbXBfY29tcF92ZWNbIkF1dHVtbiJdKSwgCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsgIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IHNlYXNvbiwKICAgICAgICAgICAgICAgICAgIHk9dGVtcCArIDEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHJvdW5kKHRlbXAsIGRpZ2l0cyA9IDEpKSkrCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMS40LCB5ID0gMS41LCBsYWJlbCA9IHBhc3RlMCgiaW50ZXJjZXB0PSIscm91bmQodGVtcF9jb21wX3ZlY1siV2ludGVyIl0sIGRpZ2l0cyA9IDEpKSkpKwogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDMuNiwgeSA9IDUsIGxhYmVsID0gcGFzdGUwKCJhdXR1bW49KyIscm91bmQodGVtcF9jb2VmWyJBdXR1bW4iXSwgZGlnaXRzID0gMSkpKSkrCiAgICB4bGltKCJXaW50ZXIiLCAiU3ByaW5nIiwgIlN1bW1lciIsICJBdXR1bW4iKSsKICAgIHlsaW0odGVtcF9yYW5nZVsxXSwgdGVtcF9yYW5nZVsyXSkrCiAgICB0aGVtZV9idygpCmBgYAoKTGV0J3MgcmV2aWV3IHRoZSBzdW1tYXJ5IG9mIHRoZSBtb2RlbCBhZ2FpbjoKCgpgYGB7ciBlY2hvID0gVH0Kc3VtbWFyeShzZWFzb25fbW9kZWwpCmBgYAoKV2UgY2FuIHNheSB0aGUgZm9sbG93aW5nIHRoaW5ncyBhYm91dCB0aGlzIG1vZGVsOgoKLSBUaGUgc2lnbmlmaWNhbnQgYChJbnRlcmNlcHQpYCBlZmZlY3QgbWVhbnMgdGhlIGF2ZXJhZ2UgdGVtcGVyYXR1cmUgaW4gV2ludGVyIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gMCAoZXN0aW1hdGVkIHRvIGJlIDIuNykuCi0gVGhlIHNpZ25pZmljYW50IGBzZWFzb25TcHJpbmdgIGVmZmVjdCBtZWFucyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIFNwcmluZyBhbmQgV2ludGVyIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gMCAoU3ByaW5nIGlzIGVzdGltYXRlZCB0byBiZSA1LjMgZGVncmVlZXMgd2FybWVyIHRoYW4gV2ludGVyLikKLSBUaGUgc2lnbmlmaWNhbnQgYHNlYXNvblN1bW1lcmAgZWZmZWN0IG1lYW5zIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gU3VtbWVyIGFuZCBXaW50ZXIgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSAwIChTdW1tZXIgaXMgZXN0aW1hdGVkIHRvIGJlIDEwLjcgZGVncmVlZXMgd2FybWVyIHRoYW4gV2ludGVyLikKLSBUaGUgc2lnbmlmaWNhbnQgYHNlYXNvbkF1dHVtbmAgZWZmZWN0IG1lYW5zIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gQXV0dW1uIGFuZCBXaW50ZXIgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSAwIChBdXR1bW4gaXMgZXN0aW1hdGVkIHRvIGJlIDcgZGVncmVlZXMgd2FybWVyIHRoYW4gV2ludGVyLikKCkFuZCB0aGF0IGlzIHByZXR0eSBtdWNoICphbGwqIHdlIGNhbiBzYXkuIExvb2tpbmcgYXQgdGhlc2UgcmVzdWx0cywgd2UgY2FuIHNheSB0aGF0IFNwcmluZyBpcyBzaWduaWZpY2FudGx5IHdhcm1lciB0aGFuIFdpbnRlciwgYnV0IHdlICpjYW4ndCogc2F5IGFueXRoaW5nIGFib3V0IGEgZ2VuZXJpYyAiZWZmZWN0IG9mIFNwcmluZy4iCkluIGZhY3QsICp3aGF0IHdvdWxkIHdlIG1lYW4gYnkgc3VjaCBhIHRoaW5nIGFueXdheT8qCgpXZSBhbHNvIGNhbid0IHNheSBhbnl0aGluZyBhYm91dCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGFueSBvZiB0aGUgb3RoZXIgc2Vhc29ucy4KRm9yIGV4YW1wbGUsIFNwcmluZyBhbmQgQXV0dW1uIGhhdmUgdmVyeSBzaW1pbGFyIGxvb2tpbmcgdGVtcGVyYXR1cmVzICh0aGVpciBkaWZmZXJlbmNlIGZyb20gV2ludGVyIGlzIHZlcnkgc2ltaWxhcikuIFdlIGNhbid0IHNheSBhbnl0aGluZyBhYm91dCB3aGV0aGVyIG9yIG5vdCBTcHJpbmcgaXMgd2FybWVyIG9yIGNvb2xlciB0aGFuIEF1dHVtbi4gCgojIEEgbW9yZSBwcmFjdGljYWwgZXhhbXBsZSAtIFNjYWxpbmcgYW5kIHRyYW5zb3JtaW5nIHByZWRpY3RvcnMKCldlJ3JlIG5vdyBnb2luZyB0byB3YWxrIHRocm91Z2ggYSByZWFsIGV4YW1wbGUgZnJvbSBteSBvd24gcmVzZWFyY2ggaW52b3ZsaW5nIHRoZSB2b3dlbCAvYXkvLiBJbiB0aGlzIGV4YW1wbGUsIHdlJ3JlIGdvaW5nIHRvIGJlIHdhbGtpbmcgdGhyb3VnaCAKCjxkaXYgY2xhc3MgPSAiYm94IGJyZWFrIj4KPHNwYW4gY2xhc3MgPSAiYmlnLWxhYmVsIj5CcmllZiBCYWNrZ3JvdW5kIG9uIC9heS88L3NwYW4+CgpUaGUgRW5nbGlzaCB2b3dlbCAvYXkvIGlzIHRoZSB2b3dlbCBzb3VuZCB0aGF0IGFwcGVhcnMgaW4gdGhlIEVuZ2xpc2ggd29yZHMgKnJpZGUqIGFuZCAqcHJpY2UqLiBJdCBpcyBhICJkaXBodGhvbmciLCBtZWFuaW5nIGl0IGlzIGEgc291bmQgd2l0aCB0d28gZGlmZmVyZW50IGFydGljdWxhdG9yeSB0YXJnZXRzLiBJbiB0aGUgZGlhbGVjdCB0aGlzIGRhdGEgaXMgZHJhd24gZnJvbSwgdGhlIGZpcnN0IHRhcmdldCBpcyBzb21ldGhpbmcgbGlrZSBhIGxvdyBhbmQgYmFjayBbyZFdLCB3aGljaCBhcHBlYXJzIGluIHRoZSB3b3JkcyAqaG90KiBhbmQgKmxvdCosIGFuZCB0aGUgc2Vjb25kIHRhcmdldCBpcyBzb21ldGhpbmcgbGlrZSBhIGhpZ2ggYW5kIGZyb250IFtpOl0sIHdoaWNoIHNob3dzIHVwIGluIHRoZSB3b3JkcyAqZmxlZWNlKiBhbmQgKmhlYXQqLiBXZSdsbCBiZSBmb2N1c2luZyBvbiBqdXN0IHRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBkaXBodGhvbmcsIHRoZSB0eXBpY2FsbHkgbG93IGFuZCBiYWNrIHBhcnQuCgpWb3dlbCBzb3VuZHMgY2FuIGJlIGNoYXJhY3Rlcml6ZWQgdXNpbmcgYm90aCBhcnRpY3VsYXRvcnkgYW5kIGFjb3VzdGljIG1lYXN1cmVzLCBhbmQgaXQgaGFzIGJlZW4gZm91bmQgdGhhdCBjZXJ0YWluIGFjb3VzdGljIGZlYXR1cmVzIGNhbiBiZSByZWxpYWJseSBjb3JyZWxhdGVkIHdpdGggdGhlIGFydGljdWxhdG9yeSBwb3NpdGlvbiBvZiB0aGUgdG9uZ3VlIHdoaWxlIHRoZSB2b3dlbHMgYXJlIHByb2R1Y2VkLiBUaGlzIG1lYW5zIHdlIGNhbiBjaGFyYWN0ZXJpemUgc3BlYWtlcnMnIHByb251bmNpYXRpb25zIG9mIHZvd2VsIHNvdW5kcyBmcm9tIGp1c3QgYSByZWNvcmRpbmcgb2YgdGhlaXIgc3BlZWNoLiBJZiB3ZSBleGFtaW5lIGhvdyB0aGVzZSBhY291c3RpYyBwcm9wZXJ0aWVzIG9mIHZvd2VscyBjb3Zhcnkgd2l0aCBzcGVha2VycycgYWdlcyBvciBkYXRlcyBvZiBiaXJ0aCwgd2UgY2FuIGFsc28gZXN0aW1hdGUgaG93IHByb251bmNpYXRpb25zIG9mIHRoZXNlIHZvd2VscyBoYXZlIGNoYW5nZWQgb3ZlciB0aW1lLiAKClRoZXNlIGFjb3VzdGljIHByb3BlcnRpZXMgYXJlIGNhbGxlZCAiZm9ybWFudHMiLCBhbmQgdGhlIGZvcm1hbnQgd2UgYXJlIGdvaW5nIGZvY3VzIG9uIGhlcmUgaXMgIkYxIiwgd2hpY2ggY292YXJpZXMgd2l0aCB0aGUgaGVpZ2h0IG9mIHRoZSB0b25ndWUgaW4gdGhlIG1vdXRoLiBUaGUgaGlnaGVyIEYxLCB0aGUgKmxvd2VyKiBpbiB0aGUgdGhlIG1vdXRoIHRoZSB0b25ndWUgaXMuIEl0J3MgYWxzbyB0aGUgY2FzZSB0aGF0IEYxIHZhbHVlcyBzeXN0ZW1hdGljYWxseSBjb3Zhcnkgd2l0aCB0aGUgbGVuZ3RoIG9mIHNwZWFrZXJzJyB2b2NhbCB0cmFjdHMsIHNvIHdlIGFyZSBhY3R1YWxseSBnb2luZyB0byBiZSBsb29raW5nIGF0ICpub3JtYWxpemVkIEYxKiwgd2hpY2ggYXR0ZW1wdHMgdG8gZmFjdG9yIG91dCB0aGlzIGVmZmVjdC4KPC9kaXY+CgpGb3IgdGhpcyBpbGx1c3RyYXRpb24sIHdlJ3JlIGdvaW5nIHRvIGZpcnN0IGZvY3VzIG9uIHRoZSB2b3dlbCAvYXkvIGJlZm9yZSB2b2ljZWxlc3MgY29uc29uYW50cyAoaS5lLiAvcCwgdCwgaywgZiwgcy8pLgpJbiBQaGlsYWRlbHBoaWEsIHdoZXJlIHRoaXMgZGF0YSBpcyBmcm9tLCAvYXkvIHVuZGVyd2VudCBhIGZhaXJseSBsYXJnZSBzaGlmdCBpbiBpdHMgcHJvbnVuY2lhdGlvbiBhY3Jvc3MgdGhlIDIwdGggY2VudHVyeS4KCmBgYHtyfQpheVRfbWVhbnMgPC0gYXkgJT4lCiAgZmlsdGVyKHBsdF92Y2xhc3MgPT0gImF5MCIgKSU+JSAgIyBnZXQgdGhlIHByZS12b2ljZWxlc3MgdG9rZW5zCiAgbXV0YXRlKGRvYiA9IHllYXIgLSBhZ2UpICU+JSAgICAgIyBjYWxjdWxhdGUgc3BlYWtlcnMnIGRvYgogIGdyb3VwX2J5KGlkc3RyaW5nLCBkb2IpICU+JSAgICAgICMgcHJlcGFyZSB0byBlc3RpbWF0ZSBieS1zcGVha2VyIG1lYW5zCiAgc3VtbWFyaXNlKEYxX24gPSBtZWFuKEYxX24pKSAgICAgIyBtZWFucwpgYGAKCmBgYHtyfQpheVRfbWVhbnMgJT4lCiAgZ2dwbG90KGFlcyhkb2IsIEYxX24pKSsKICAgIGdlb21fcG9pbnQoKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpJbiB0aGlzIHBsb3QsIGVhY2ggcG9pbnQgcmVwcmVzZW50cyBvbmUgc3BlYWtlci4KRWFjaCBzcGVha2VyJ3MgYXZlcmFnZSBub3JtYWxpemVkIEYxIHZhbHVlIGlzIHBsb3R0ZWQgYWdhaW5zdCB0aGVpciBkYXRlIG9mIGJpcnRoIChyYW5naW5nIGZyb20gMTg4OSB0byAxOTk4KS4KRml0dGluZyBhIGxpbmVhciBtb2RlbCB0byB0aGlzIGRhdGEgYXBwZWFycyBlYXN5LCBidXQgYWN0dWFsbHkgcG9zZXMgdXMgd2l0aCBpbnRlcnByZXRpdmUgY2hhbGxlbmdlcy4gCgpgYGB7cn0KYXlUX21vZGVsMSA8LSBsbShGMV9uIH4gZG9iLCBkYXRhID0gYXlUX21lYW5zKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGF5VF9tb2RlbDEpCmBgYAoKTGV0J3Mgc29ydCBvdXQgd2hhdCBpcyBiZWluZyByZXBvcnRlZCBoZXJlIGluIHRoaXMgbW9kZWwsIHN0YXJ0aW5nIHdpdGggdGhlIGludGVyY2VwdC4KCmBgYAogICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKKEludGVyY2VwdCkgMjUuODEwMDk3MCAgMS4wMjMyMTQ2ICAgMjUuMjMgICA8MmUtMTYgKioqCmBgYAoKV2Ugc2VlIGhlcmUgdGhhdCB0aGUgaW50ZXJjZXB0IGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gMCwgYnV0IHdoYXQgZG9lcyB0aGlzIGludGVyY2VwdCBtZWFuPyAKVGhlIGludGVyY2VwdCBpcyB0aGUgZXN0aW1hdGVkIHZhbHVlIG9mIHRoZSBvdXRjb21lIHZhcmlhYmxlIHdoZW4gdGhlIHByZWRpY3RvciBpcyAwLCBtZWFuaW5nIHRoZSBtb2RlbCBpcyBwcmVkaWN0aW5nIGEgdmFsdWUgb2Ygbm9ybWFsaXplZCBGMSBvZiBhYm91dCAyNiBmb3Igc3BlYWtlcnMgYm9ybiBpbiB0aGUgeWVhciAwLgoKCmBgYHtyIGVjaG8gPSBGfSAKYXlUX21lYW5zICU+JQogIGdncGxvdChhZXMoZG9iLCBGMV9uKSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHkgPSAwLCB5ZW5kID0gMjUuOCwgeD0wLCB4ZW5kPTApLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICB0aGVtZV9idygpCmBgYAoKVGhpcyBpcyBvYnZpb3VzbHkgcHJvYmxlbWF0aWMuIApGaXJzdCwgdGhpcyBpcyBhICJzaWduaWZpY2FudCIgZWZmZWN0LCBidXQgaXQgZXh0cmFwb2xhdGVzIHNvIGZhciBiZXlvbmQgdGhlIGRhdGEgdGhhdCBpdCdzIGVudGlyZWx5IG1lYW5pbmdsZXNzLiAoTm9ib2R5IHdhcyBzcGVha2luZyAiRW5nbGlzaCIgaW4gdGhlIHllYXIgMC4pClNlY29uZCwgdGhpcyBlc3RpbWF0ZWQgbm9ybWFsaXplZCBGMSB2YWx1ZSBpcyBub3QgYSBwbGF1c2libGUgRjEgdmFsdWUgZm9yICphbnkqIHZvd2VsLiAKSWYgeW91IHdlcmUgdG8gdHJ5IHRvIG1hcCB0aGlzIG9udG8gYW4gYXJ0aWN1bGF0b3J5IHN0cmF0ZWd5LCBzcGVha2VyJ3MgdG9uZ3VlIGJvZGllcyB3b3VsZCBiZSBkb3duIHNvbWV3aGVyZSBhcm91bmQgdGhlaXIgYW5rbGVzLgoKTGV0J3MgYWxzbyBsb29rIGF0IHRoZSBzbG9wZS4gCgpgYGAKICAgICAgICAgICAgICBFc3RpbWF0ZSBTdGQuIEVycm9yIHQgdmFsdWUgUHIoPnx0fCkgICAgCmRvYiAgICAgICAgIC0wLjAxMjk3MTAgIDAuMDAwNTI2MiAgLTI0LjY1ICAgPDJlLTE2ICoqKgpgYGAKClRoaXMgbWVhbnMgZm9yIGV2ZXJ5IDEgdW5pdCBpbmNyZWFzZSBpbiBgZG9iYCAoaS5lLiAxIHllYXIpLCB0aGVyZSBpcyBhIGRlY3JlYXNlIG9mIC0wLjAxMyBpbiBub3JtYWxpemVkIEYxLgoKCmBgYHtyIGVjaG8gPSBGfSAKYXlUX21lYW5zICU+JQogIGdncGxvdChhZXMoZG9iLCBGMV9uKSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHkgPSAwLCB5ZW5kID0gMjUuOCwgeD0wLCB4ZW5kPTApLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAyNS44LCBzbG9wZSA9IC0wLjAxMywgY29sb3IgPSAicmVkIikrCiAgICB0aGVtZV9idygpCmBgYAoKCgpJZiB3ZSBpZ25vcmUgdGhlIGNvbWljYWxseSB3ZWlyZCBpbnRlcmNlcHQsIHRoaXMgc2xvcGUgaXMgbGVzcyBwcm9ibGVtYXRpYy4gVGhlIG9uZSBtYWpvciBpc3N1ZSBpbiBpdCBpcyBpdHMgb3ZlcnNwZWNpZmljaXR5LgpUaGlzIHNsb3BlIGlzIGRlZmluZWQgaW4gdGVybXMgb2YgYSBjaGFuZ2UgaW4gMSB5ZWFyIG9mIGRhdGUgb2YgYmlydGgsIGJ1dCBpbiBhbiBpbXBvcnRhbnQgc2Vuc2UgdGhhdCdzIG92ZXIgcHJlY2lzZS4gCldlIHdvdWxkbid0ICpyZWFsbHkqIHdhbnQgdG8gbWFrZSBhbnkgc3Ryb25nIGluZmVyZW5jZXMgYWJvdXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBzcGVha2VycycgYm9ybiBpbiAxOTY5IGFuZCAxOTcwLCBmb3IgZXhhbXBsZS4KCiMjIFJlc2NhbGluZwoKV2UgY2FuIGFkZHJlc3MgdGhlc2UgcHJvYmxlbXMgd2l0aCB0aGUgbW9kZWtsIGJ5ICpyZXNjYWxpbmcqIHRoZSBkYXRlIG9mIGJpcnRoIHByZWRpY3Rvci4KUmVzY2FsaW5nIHByZWRpY3RvcnMgaXMgbm90IG9ubHkgImFsbG93ZWQsIiBpdCBjYW4gYmUgKmNydWNpYWwqIHdoZW4gaXQgY29tZXMgdG8gdHJ5aW5nIHRvIGZpdCBtaXhlZCBlZmZlY3RzIG1vZGVscyEKCjxkaXYgY2xhc3MgPSAiYm94IGlkaW9tIj4KPHNwYW4gY2xhc3MgPSAibGFiZWwiPklkaW9tPC9zcGFuPgoKTm90IHRvIGNvbmZ1c2UgdGhpbmdzIHRvbyBtdWNoLCBidXQgdHJhbnNvcm1hdGlvbnMgeW91IG1ha2UgdG8gcHJlZGljdG9ycyBjYW4gYmUgbHVtcGVkIGludG8gdHdvIGJyb2FkIGNhdGVnb3JpZXM6ICpsaW5lYXIqIGFuZCAqbm9uLWxpbmVhciouIApUaGlzIHVzZSBvZiAibGluZWFyIiBpc24ndCByZWxhdGVkIHRvIGxpbmVhciByZWdyZXNzaW9uIGluIGFueSB3YXkuCkluc3RlYWQsIGl0IGRlc2NyaWJlcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIG9yaWdpbmFsIG1lYXN1cmUgYW5kIHRoZSB0cmFuc2Zvcm1lZCBtZWFzdXJlLgoKIyMjIyBMaW5lYXIgdHJhbnNmb3JtYXRpb25zIGFyZToKCi0gYWRkaXRpb24sIHN1YnRyYWN0aW9uLCBtdWx0aXBsaWNhdGlvbiwgZGl2aXNpb24KClByb29mIGJ5IHNpbXVsYXRpb246CgpgYGB7ciBlY2hvID0gVH0KbGluZWFyX2RmIDwtIGRhdGFfZnJhbWUob3JpZ2luYWwgPSBybm9ybSgxMDAsIG1lYW4gPSA1MCksCiAgICAgICAgICAgICAgICAgICAgICAgIGFkZGl0aW9uID0gb3JpZ2luYWwgKyAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgc3VidHJhY3Rpb24gPSBvcmlnaW5hbCAtIDEwLAogICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsaWNhdGlvbiA9IG9yaWdpbmFsICogMTAsCiAgICAgICAgICAgICAgICAgICAgICAgIGRpdmlzaW9uID0gb3JpZ2luYWwvMTApCmBgYAoKPGRpdiBzdHlsZSA9ICJ3aWR0aDoxMDAlO2Zsb2F0OmxlZnQ7Ij4KPGRpdiBzdHlsZSA9ICJ3aWR0aDoyMyU7IGZsb2F0OmxlZnQ7IG1hcmdpbjphdXRvOyI+CmBgYHtyIGVjaG8gPSBGLCBmaWcud2lkdGggPSAxLCBmaWcuaGVpZ2h0ID0gMSwgb3V0LndpZHRoPSIxMDAlIn0KZ2dwbG90KGxpbmVhcl9kZiwgYWVzKG9yaWdpbmFsLCBhZGRpdGlvbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgiYWRkaXRpb24iKQpgYGAKPC9kaXY+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlO2Zsb2F0OmxlZnQ7bWFyZ2luLWxlZnQ6MSU7Ij4KYGBge3IgZWNobyA9IEYsZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChsaW5lYXJfZGYsIGFlcyhvcmlnaW5hbCxzdWJ0cmFjdGlvbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgic3VidHJhY3Rpb24iKQpgYGAKPC9kaXY+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlO2Zsb2F0OmxlZnQ7bWFyZ2luLWxlZnQ6MSU7Ij4KYGBge3IgZWNobyA9IEYsZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChsaW5lYXJfZGYsIGFlcyhvcmlnaW5hbCxtdWx0aXBsaWNhdGlvbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgibXVsdGlwbGljYXRpb24iKQpgYGAKPC9kaXY+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlO2Zsb2F0OmxlZnQ7bWFyZ2luLWxlZnQ6MSU7Ij4KYGBge3IgZWNobyA9IEYsZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChsaW5lYXJfZGYsIGFlcyhvcmlnaW5hbCxkaXZpc2lvbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgiZGl2aXNpb24iKQpgYGAKPC9kaXY+CjwvZGl2PgoKQW55IGNvbWJpbmF0aW9uIG9mIChvbmx5KSBsaW5lYXIgdHJhbnNmb3JtcyBpcyBhIGxpbmVhciB0cmFuc2Zvcm0uCgojIyMjIE5vbi1saW5lYXIgdHJhbnNmb3JtYXRpb25zIGFyZToKCi0gbG9nYXJpdGhtcyAoYW55IGJhc2UpLCBjb3NpbmUsIHNxdWFyZSByb290LCBldGMuCgpQcm9vZiBieSBzaW11bGF0aW9uOgpgYGB7ciBlY2hvID0gVH0Kbm9ubGluZWFyX2RmIDwtIGRhdGFfZnJhbWUob3JpZ2luYWwgPSBybm9ybSgxMDAsIG1lYW4gPSA1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nX3RlbiA9IGxvZzEwKG9yaWdpbmFsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29zaW5lID0gY29zKG9yaWdpbmFsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3F1YXJlX3Jvb3QgPSBzcXJ0KG9yaWdpbmFsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwb25lbnRpYWwgPSBleHAob3JpZ2luYWwpKQpgYGAKCjxkaXYgc3R5bGUgPSAid2lkdGg6MTAwJTtmbG9hdDpsZWZ0OyI+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlOyBmbG9hdDpsZWZ0OyBtYXJnaW46YXV0bzsiPgpgYGB7ciBlY2hvID0gRiwgZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChub25saW5lYXJfZGYsIGFlcyhvcmlnaW5hbCwgbG9nX3RlbikpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfbWluaW1hbCgpKwogICAgZ2d0aXRsZSgibG9nMTAiKQpgYGAKPC9kaXY+CjxkaXYgc3R5bGUgPSAid2lkdGg6MjMlO2Zsb2F0OmxlZnQ7bWFyZ2luLWxlZnQ6MSU7Ij4KYGBge3IgZWNobyA9IEYsZmlnLndpZHRoID0gMSwgZmlnLmhlaWdodCA9IDEsIG91dC53aWR0aD0iMTAwJSJ9CmdncGxvdChub25saW5lYXJfZGYsIGFlcyhvcmlnaW5hbCxjb3NpbmUpKSsKICAgIGdlb21fcG9pbnQoKSsKICAgIHRoZW1lX21pbmltYWwoKSsKICAgIGdndGl0bGUoImNvc2luZSIpCmBgYAo8L2Rpdj4KPGRpdiBzdHlsZSA9ICJ3aWR0aDoyMyU7ZmxvYXQ6bGVmdDttYXJnaW4tbGVmdDoxJTsiPgpgYGB7ciBlY2hvID0gRixmaWcud2lkdGggPSAxLCBmaWcuaGVpZ2h0ID0gMSwgb3V0LndpZHRoPSIxMDAlIn0KZ2dwbG90KG5vbmxpbmVhcl9kZiwgYWVzKG9yaWdpbmFsLHNxdWFyZV9yb290KSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICB0aGVtZV9taW5pbWFsKCkrCiAgICBnZ3RpdGxlKCJzcXVhcmUgcm9vdCIpCmBgYAo8L2Rpdj4KPGRpdiBzdHlsZSA9ICJ3aWR0aDoyMyU7ZmxvYXQ6bGVmdDttYXJnaW4tbGVmdDoxJTsiPgpgYGB7ciBlY2hvID0gRixmaWcud2lkdGggPSAxLCBmaWcuaGVpZ2h0ID0gMSwgb3V0LndpZHRoPSIxMDAlIn0KZ2dwbG90KG5vbmxpbmVhcl9kZiwgYWVzKG9yaWdpbmFsLGV4cG9uZW50aWFsKSkrCiAgICBnZW9tX3BvaW50KCkrCiAgICB0aGVtZV9taW5pbWFsKCkrCiAgICBnZ3RpdGxlKCJleHBvbmVudGlhbCIpCmBgYAo8L2Rpdj4KPC9kaXY+Cgo8L2Rpdj4KCklmIHdlIGFwcGx5IG9uZSwgb3IgbWFueSwgKmxpbmVhciogdHJhbnNmb3JtYXRpb25zIHRvIHRoZSBwcmVkaWN0b3IgdmFyaWFibGUsIHdlIHdvbid0IGFmZmVjdCB0aGUgZ29vZG5lc3Mgb2YgZml0IG9mIHRoZSBtb2RlbCwgbm9yIHRoZSBzaWduaWZpY2FuY2Ugb3Igc2lnbiBvZiB0aGF0IHByZWRpY3Rvci4KQnV0IGl0IHdpbGwgY2hhbmdlIHRoZSB3YXkgd2UgKmludGVycHJldCogdGhlIGVmZmVjdHMuCgpUaGVyZSBhcmUgYSBmZXcgZGlmZmVyZW50IGtpbmRzIG9mIHRyYW5zZm9ybWF0aW9ucyB3ZSBjYW4gZG8uIApBIHZlcnkgY29tbW9uIGtpbmQgb2YgdHJhbnNmb3JtYXRpb24gaXMgdG8gKip6LXNjb3JlKiogdGhlIGRhdGEuClRvIHotc2NvcmUgbnVtZXJpYyBkYXRhLCB5b3UgKnN1YnRyYWN0IHRoZSBtZWFuKiBhbmQgKmRpdmlkZSBieSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uKi4KSGVyZSdzIGhvdyB0aGF0IGxvb2tzIGluIG1hdGhlbWF0aWNhbCBub3RhdGlvbgoKJCQKeiA9IFxmcmFje3gtXG11fXtcc2lnbWF9CiQkCgpXaGVyZSAkXG11JCBpcyB0aGUgbWVhbiBvZiB0aGUgJHgkIGRhdGEsIGFuZCAkXHNpZ21hJCBpcyB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uLgpIZXJlJ3MgaG93IHRoYXQgbG9va3MgaW4gcHJhY3RpY2UuIApUaGUgZGF0ZSBvZiBiaXJ0aCBvZiBzcGVha2VycyBoYXMgdGhlIGZvbGxvd2luZyBkaXN0cmlidXRpb24gb2YgZGF0YSwgd2l0aCB0aGUgbWVhbmQgYW5kICRccG0xJCBzdGFuZGFyZCBkZXZpYXRpb24gYW5ub3RhdGVkLgoKCgpgYGB7ciBlY2hvID0gRn0KbWVhbl9kb2IgPC0gbWVhbihheVRfbWVhbnMkZG9iKQpzZF9kb2IgPC0gc2QoYXlUX21lYW5zJGRvYikKZ2dwbG90KGF5VF9tZWFucywgYWVzKGRvYikpKwogICAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJncmV5NTAiKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW5fZG9iKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSBtZWFuX2RvYiwgeSA9IDAuMDA2LCBsYWJlbCA9ICJtZWFuIikpKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbl9kb2IgKyBzZF9kb2IsIGxpbmV0eXBlID0gMikrCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gbWVhbl9kb2IgKyBzZF9kb2IsIHkgPSAwLjAwNiwgbGFiZWwgPSAiKzEgc2QiKSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuX2RvYiAtIHNkX2RvYiwgbGluZXR5cGUgPSAyKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSBtZWFuX2RvYiAtIHNkX2RvYiwgeSA9IDAuMDA2LCBsYWJlbCA9ICItMSBzZCIpKSsgICAgCiAgICB0aGVtZV9taW5pbWFsKCkrCiAgICBnZ3RpdGxlKCJPcmlnaW5hbCBTY2FsZSIpCmBgYAoKCkJ5IHN1YnRyYWN0aW5nIG91dCB0aGUgbWVhbiwgd2UgY2VudGVyIHRoaXMgZGlzdHJpYnV0aW9uIG9uIDAsIGFuZCBieSBkaXZpZGluZyBieSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uLCB3ZSBzaHJpbmsgZG93biB0aGUgZGlzdHJpYnV0aW9uIHNvIHRoYXQgMSBzdGFuZGFyZCBkZXZpYXRpb24gZnJvbSB0aGUgbWVhbiBpcyB0aGUgdmFsdWUgMS4KSGVyZSdzIGhvdyB0aGUgcmVzdWx0IGxvb2tzOgoKCgpgYGB7ciBlY2hvID0gRn0KbWVhbl9kb2IgPC0gbWVhbihheVRfbWVhbnMkZG9iKQpzZF9kb2IgPC0gc2QoYXlUX21lYW5zJGRvYikKCmF5VF9tZWFucyA8LSBheVRfbWVhbnMlPiUKICAgICAgICAgICAgICAgIHVuZ3JvdXAoKSU+JQogICAgICAgICAgICAgICAgbXV0YXRlKGRvYl96ID0gKGRvYi1tZWFuKGRvYikpL3NkKGRvYikpCmdncGxvdChheVRfbWVhbnMsIGFlcyhkb2JfeikpKwogICAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJncmV5NTAiKSsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDApKwogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDAsIHkgPSAwLjE1LCBsYWJlbCA9ICJtZWFuIikpKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAyKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAxLCB5ID0gMC4xNSwgbGFiZWwgPSAiKzEgc2QiKSkrCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAtMSwgbGluZXR5cGUgPSAyKSsKICAgIGdlb21fbGFiZWwoYWVzKHggPSAtMSwgeSA9IDAuMTUsIGxhYmVsID0gIi0xIHNkIikpKyAgICAKICAgIHRoZW1lX21pbmltYWwoKSsKICAgIGdndGl0bGUoInotU2NhbGUiKQpgYGAKCgojIyMgV2h5IGlzIHRoaXMgYW4gaW1wcm92ZW1lbnQ/IAoKTGV0J3MgcmUtZml0IHRoZSBtb2RlbCB3aXRoIHRoaXMgdHJhbnNmb3JtZWQgRE9CIHByZWRpY3RvciBhbmQgc2VlOgoKYGBge3J9CmF5VF9tb2RlbDIgPC0gbG0oRjFfbiB+IGRvYl96LCBkYXRhID0gYXlUX21lYW5zKQpzdW1tYXJ5KGF5VF9tb2RlbDIpCmBgYAoKYGBgCiAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KQooSW50ZXJjZXB0KSAgMC41ODg2MiAgICAwLjAxMjA1ICAgNDguODMgICA8MmUtMTYgKioqCmBgYAoKVGhlIGludGVyY2VwdCBpcyB0aGUgZXN0aW1hdGVkIHZhbHVlIG9mIG5vcm1hbGl6ZWQgRjEgd2hlbiBgZG9iX3pgIGlzIDAsIHdoaWNoIGlzIHRoZSBtZWFuIG9mIGRvYiwgYHIgcm91bmQobWVhbl9kb2IpYC4KCmBgYHtyIGVjaG8gPSBGfSAKYXlUX21lYW5zICU+JQogIGdncGxvdChhZXMoZG9iLCBGMV9uKSkrCiAgICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXk3MCIpKwogICAgZ2VvbV9zZWdtZW50KGFlcyh5ID0gMCwgeWVuZCA9IGNvZWYoYXlUX21vZGVsMilbMV0sIHg9bWVhbl9kb2IsIHhlbmQ9bWVhbl9kb2IpLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICB0aGVtZV9idygpCmBgYAoKCmBgYAogICAgICAgICAgICBFc3RpbWF0ZSBTdGQuIEVycm9yIHQgdmFsdWUgUHIoPnx0fCkKZG9iX3ogICAgICAgLTAuMjk3NjAgICAgMC4wMTIwNyAgLTI0LjY1ICAgPDJlLTE2ICoqKgpgYGAKClRoZSBzbG9wZSB0ZWxscyB1cyBob3cgbXVjaCBub3JtYWxpemVkIEYxIGNoYW5nZXMgZm9yIGV2ZXJ5IGNoYW5nZSBvZiAxIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBkb2IgKGByIHJvdW5kKHNkX2RvYilgIHllYXJzKQoKCkZvciBldmVyeSAxIHN0YW5kYXJkIGRldmlhdGlvbiBzaGlmdCBpbiBkb2IgKGByIHJvdW5kKHNkX2RvYilgIHllYXJzKSwgdGhlcmUgaXMgYSBkZWNyZWFzZSBvZiAwLjMgaW4gbm9ybWFsaXplZCBGMS4KCmBgYHtyIGVjaG8gPSBGfQp6X3N0ZXBfZGYgPC0gZGF0YV9mcmFtZShkb2IgPSBjKG1lYW5fZG9iIC0gc2RfZG9iLCBtZWFuX2RvYiwgbWVhbl9kb2IgKyBzZF9kb2IpLAogICAgICAgICAgICAgICAgICAgICAgICBGMV9uID0gYyhjb2VmKGF5VF9tb2RlbDIpWzFdIC0gY29lZihheVRfbW9kZWwyKVsyXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZihheVRfbW9kZWwyKVsxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bShjb2VmKGF5VF9tb2RlbDIpKSkpCgoKYXlUX21lYW5zICU+JQogIGdncGxvdChhZXMoZG9iLCBGMV9uKSkrCiAgICBnZW9tX3BvaW50KGNvbG9yID0gImdyZXk3MCIpKwogICAgZ2VvbV9zZWdtZW50KGFlcyh5ID0gMCwgeWVuZCA9IGNvZWYoYXlUX21vZGVsMilbMV0sIHg9bWVhbl9kb2IsIHhlbmQ9bWVhbl9kb2IpLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICBnZW9tX3N0ZXAoZGF0YSA9IHpfc3RlcF9kZiwgZGlyZWN0aW9uID0gJ3ZoJykrCiAgICBnZW9tX3BvaW50KGRhdGEgPSB6X3N0ZXBfZGYsIGNvbG9yID0gInJlZCIpKwogICAgdGhlbWVfYncoKQpgYGAKClRoZXNlIHZhbHVlcyBvZiB0aGUgaW50ZXJjZXB0IGFuZCBzbG9wZSBhcmUgbW9yZSAqaW50ZXJwcmV0YWJsZSouIAoKIyMjIE90aGVyIHBvc3NpYmxlIHRyYW5zZm9ybWF0aW9ucwoKVGhlIHotc2NvcmUgdHJhbnNmb3JtYXRpb24gaXNuJ3QgdGhlICpvbmx5KiB0cmFuc2Zvcm1hdGlvbiB5b3UgY2FuIHVzZS4gSXQncyBqdXN0IHRoZSBtb3N0IHN0YW5kYXJkIG9uZS4gCkZvciBleGFtcGxlLCBHZWxtYW4gJiBIaWxsICgyMDBYWCkgcmVjb21tZW5kIHVzaW5nIGEgbW9kaWZpZWQgei1zY29yZSB3aGVyZSB5b3UgZGl2aWRlIGJ5ICQyXHRpbWVzXHNpZ21hJAoKJCQKeiA9IFxmcmFje3gtXG11fXsyXHNpZ21hfQokJAoKVGhlIHJlYXNvbiB0aGVzZSBmb3JtdWxhcyB1c2UgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBpcyBiZWNhdXNlIHRoZXkgYXJlIHR3byB0aGVvcnkgbmV1dHJhbCB2YWx1ZXMgdGhhdCBjYW4gYmUgZXN0aW1hdGVkIGZvciBhbnkgc2V0IG9mIG51bWVyaWMgZGF0YS4KSG93ZXZlciwgaXQncyBwb3NzaWJsZSB0aGF0IHRoZXJlIGFyZSBtb3JlIHNlbnNpYmxlIHNjYWxpbmcgZmFjdG9ycyBmb3IgdGhlIGRhdGEgeW91J3JlIHdvcmtpbmcgd2l0aC4KRm9yIGV4YW1wbGUsIGluIG1hbnkgc29jaW9saW5ndWlzdGljIHN0dWRpZXMsIHRoZSB5ZWFyIDE5NjAgaXMgYW4gaW1wb3J0YW50IGluZmxlY3Rpb24gcG9pbnQgZm9yIG1hbnkgY2hhbmdlcy4KQW5kIGByIHJvdW5kKHNkX2RvYilgIHllYXJzIGRvZXNuJ3QgaGF2ZSBhbnkgaW50cmluc2ljIG1lYW5pbmcsIHdoaWxlIHNvbWV0aGluZyBsaWtlIDEwIHllYXJzIGlzIG1vcmUgaW50dWl0aXZlbHkgYWNjZXNzaWJsZSB0byBtb3N0IHJlYWRlcnMgKCJhIGRlY2FkZSIpLgpTbyB3ZSBjb3VsZCBqdXN0IGFzIGVhc2lsbHkgY2hvb3NlIHRoaXMgc2NhbGluZyBmb3JtdWxhIGZvciBkYXRlIG9mIGJpcnRoLgoKCiQkCmRlY2FkZSA9IFxmcmFje3ggLSAxOTYwfXsxMH0KJCQKCiMjIyBBcmUgd2UgcmVhbGx5IGFsbG93ZWQgdG8gZG8gYWxsIHRoaXMgcmVzY2FsaW5nPwoKWWVzLCBidXQsICoqeW91IG11c3QgZXhwbGFpbiB3aGF0IHlvdSBkaWQgaW4gdGhlIHdyaXRlIHVwKiouIEZvciBleGFtcGxlOgoKPiBUaGUgZGF0ZSBvZiBiaXJ0aCBwcmVkaWN0b3Igd2FzIGNlbnRlcmVkIG9uIDE5NjAsIGFuZCBkaXZpZGVkIGJ5IDEwLiBUaGUgMTk2MCB3YXMgY2hvc2VuIGFzIHRoZSBjZW50ZXJpbmcgcG9pbnQgYmVjYXVzZSBvZiBpdHMgaW1wb3J0YW5jZSBpbiBwcmV2aW91cyBzb2Npb2xpbmd1aXN0aWMgc3R1ZGllcy4gRGl2aWRpbmcgZG9iIGJ5IDEwIGdpdmVzIHRoZSByZXN1bHRpbmcgc2xvcGUgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSByYXRlIG9mIGNoYW5nZSBwZXIgZGVjYWRlLgoKCgojIE11bHRpdmFyaWF0ZSBNb2RlbHMgJiBJbnRlcmFjdGlvbnMKCldlJ3JlIHF1aWNrbHkgZ29pbmcgdG8gZ28gb3ZlciBtdWx0aXZhcmlhdGUgbW9kZWxzIChtdWx0aXBsZSBwcmVkaWN0b3JzKSBhbmQgaW50ZXJhY3Rpb25zLgpUaGUgaW1wb3J0YW50IHRoaW5nIHRvIGtlZXAgaW4gbWluZCB3aGVuIGluY2x1ZGluZyBtdWx0aXBsZSBwcmVkaWN0b3IgaXMgdGhhdCB5b3VyIHJlZmVyZW5jZSBsZXZlbCBhbmQgc2NhbGluZyBvZiBlYWNoIHByZWRpY3RvciBpcyBnb2luZyB0byBzdGFydCB0byBtYXR0ZXIgYSAqbG90KiBtb3JlLgoKCiMjIENvbnRpbmlvdXMgYW5kIGNhdGVnb3JpY2FsIHByZWRpY3RvcnMKCkxldCdzIHN0YXJ0IHdpdGggdGhlIC9heS8gZGF0YS4gUHJldmlvdXNseSB3ZSB3ZXJlIGxvb2tpbmcgb25seSBhdCBwcmUtdm9pY2VsZXNzIC9heS8uIEJ1dCBub3cgd2UncmUgZ29pbmcgdG8gbG9vayBhdCBhbGwgL2F5Lywgd2l0aCBlYWNoIHRva2VuIGNvZGVkIGZvciB3aGV0aGVyIGl0J3MgcHJlLXZvaWNlbGVzcywgb3IgZWxzZXdoZXJlLiBUaGlzIGlzIGVuY29kZWQgaW4gdGhlIGBwbHRfdmNsYXNzYCBjb2x1bW4uCgotIGBwbHRfdmNsYXNzYAogICAgLSBgYXkwYCAtIFByZS12b2ljZWxlc3MgL2F5LwogICAgLSBgYXlgIC0gQWxsIG90aGVyIC9heS8uCiAgICAKICAgIApCZWNhdXNlIHdlJ3JlIG5vdCBkZWFsaW5nIHdpdGggbWl4ZWQgZWZmZWN0cyBtb2RlbHMgeWV0LCB3ZSdsbCBmaXJzdCBjYWxjdWxhdGUgYnktc3BlYWtlciBtZWFucy4gSW4gdGhlIHByb2Nlc3MgSSdsbCBiZSByZS1zY2FsaW5nIGRhdGUgb2YgYmlydGggd2l0aCB0d28gZGlmZmVyaW5nIGNlbnRlcmluZyBwb2ludHMsIG9uZSBvbiAxOTAwLCBhbmQgb25lIG9uIDE5NjAuCgoKYGBge3J9CmF5X21lYW5zIDwtIGF5ICU+JQogICAgICAgICAgICAgIG11dGF0ZShkb2IgPSB5ZWFyLWFnZSkgJT4lCiAgICAgICAgICAgICAgZ3JvdXBfYnkoaWRzdHJpbmcsIGRvYiwgcGx0X3ZjbGFzcykgJT4lCiAgICAgICAgICAgICAgc3VtbWFyaXNlKEYxX24gPSBtZWFuKEYxX24pKSU+JQogICAgICAgICAgICAgIG11dGF0ZShkZWNhZGVfMTkwMCA9IChkb2IgLSAxOTAwKS8xMCwKICAgICAgICAgICAgICAgICAgICAgZGVjYWRlXzE5NjAgPSAoZG9iIC0gMTk2MCkvMTAsCiAgICAgICAgICAgICAgICAgICAgIHZvaWNpbmcgPSBmYWN0b3IocmVjb2RlKHBsdF92Y2xhc3MsIGF5MCA9ICJ2b2ljZWxlc3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheSA9ICJlbHNlIikpLAogICAgICAgICAgICAgICAgICAgICB2b2ljaW5nID0gcmVsZXZlbCh2b2ljaW5nLCAiZWxzZSIpKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludCgpKwogICAgdGhlbWVfYncoKQpgYGAKCiMjIFR3byBwcmVkaWN0b3JzLCBubyBpbnRlcmFjdGlvbnMKCldlIGNhbiBzZWUgdGhhdCB0aGVyZSBpcyBhICpiaWcqIGRpZmZlcmVuY2UgYmV0d2VlbiBwcmUtdm9pY2VsZXNzIGFuZCBlbHNld2hlcmUgL2F5Ly4gTGV0J3Mgc3RhcnQgYnVpbGRpbmcgdXAgdGhlIG1vZGVsIHRoZW4KCgpgYGB7cn0KYXlfbW9kZWwxIDwtIGxtKEYxX24gfiBkZWNhZGVfMTkwMCArIHZvaWNpbmcsIGRhdGEgPSBheV9tZWFucykKYGBgCgpgYGB7cn0Kc3VtbWFyeShheV9tb2RlbDEpCmBgYAoKCkxldCdzIHdhbGsgdGhyb3VnaCB0aGUgZWZmZWN0cyBieSBkcmF3aW5nIHRoZSBncmFwaCB0aGF0IHRoaXMgbW9kZWwgaXMgYSByZWNpcGUgZm9yLiBGaXJzdCwgd2UgaGF2ZSB0aGUgSW50ZXJjZXB0LgoKYGBgCiAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKKEludGVyY2VwdCkgICAgICAgMS41Njc1NzcgICAwLjAyMDg2MiAgIDc1LjE0ICAgPDJlLTE2ICoqKgpgYGAKClRoaXMgaXMgdGhlIGVzdGltYXRlZCBhdmVyYWdlIHZhbHVlIG9mIG5vcm1hbGl6ZWQgRjEgZm9yIHdoZW4gKmFsbCBwcmVkaWN0b3JzIGFyZSAwLiogClRoYXQgbWVhbnMgdGhpcyBpcyB0aGUgcHJlZGljdGVkIGludGVyY2VwdCB3aGVuIHRoZSBjZW50ZXJlZCBkb2IgaXMgMCAoMTkwMCksIGZvciB0aGUgKnJlZmVyZW5jZSBsZXZlbCogKGVsc2V3aGVyZSAvYXkvKQoKCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCB4ZW5kID0gMTkwMCwgeSA9IDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDEpWzFdLCAKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSwKICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEYpKwogICAgdGhlbWVfYncoKQpgYGAKCk5leHQgdGhlcmUncyB0aGUgc2xvcGU6IAoKYGBgCiAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKKEludGVyY2VwdCkgICAgICAgMS41Njc1NzcgICAwLjAyMDg2MiAgIDc1LjE0ICAgPDJlLTE2ICoqKgpgYGAKClRoZXJlJ3MgYSBmZXcgZGlmZmVyZW50IHdheXMgd2UgY291bGQgY29uc3RydWUgdGhpcyBzbG9wZS4gVGhlIHZhbHVlIGlzIHRoZSByYXRlIG9mIGNoYW5nZSBwZXIgZGVjYWRlLCBhbmQgd2UnbGwgaW50ZXJwcmV0IHRoaXMgYXMgdGhlIHNsb3BlIGZvciByZWZlcmVuY2UgbGV2ZWwuCgpgYGB7ciBlY2hvID0gRn0KYmFkbW9kIDwtIGxtKEYxX24gfiBkb2IgKyB2b2ljaW5nLCBkYXRhID0gYXlfbWVhbnMpCgpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCB4ZW5kID0gMTkwMCwgeSA9IDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDEpWzFdLCAKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSwKICAgICAgICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEYpKwogICAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IGNvZWYoYmFkbW9kKVsxXSwKICAgICAgICAgICAgICAgIHNsb3BlID0gY29lZihiYWRtb2QpWzJdLAogICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIHRoZW1lX2J3KCkKYGBgCgoKRmluYWxseSwgdGhlcmUncyB0aGUgdm9pY2luZyBwYXJhbWV0ZXIuIAoKYGBgCiAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKdm9pY2luZ3ZvaWNlbGVzcyAtMC42NDMzNTcgICAwLjAxNzM3NiAgLTM3LjAyICAgPDJlLTE2ICoqKgpgYGAKClRoaXMgdGVsbHMgdXMgaG93IGRpZmZlcmVudCB0aGUgKmludGVyY2VwdCogb2YgdGhlIGxpbmUgZm9yIHByZS12b2ljZWxlc3MgL2F5LyBpcyBmcm9tIGVsc2V3aGVyZSAvYXkvLgpCZWNhdXNlIHdlIGhhdmUgaW5jbHVkZWQgbm8gb3RoZXIgZWZmZWN0cyBvciBpbnRlcmFjdGlvbnMsIHRoZSBtb2RlbCBpcyBhc3N1bWluZyB0aGF0IHRoZSBzbG9wZSBvZiB0aGUgcHJlLXZvaWNlbGVzcyAvYXkvIGlzICppZGVudGljYWwqIHRvIGVsc2V3aGVyZSAvYXkvLgoKCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCAKICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IDE5MDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDEpWzFdICsgY29lZihheV9tb2RlbDEpWzNdICwgCiAgICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKGF5X21vZGVsMSlbMV0pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQgPSBjb2VmKGJhZG1vZClbMV0sCiAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kKVsyXSwKICAgICAgICAgICAgICAgIGNvbG9yID0gImVsc2UiKSwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QpWzFdICsgY29lZihiYWRtb2QpWzNdLAogICAgICAgICAgICAgICAgc2xvcGUgPSBjb2VmKGJhZG1vZClbMl0sCiAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrICAKICAgIHRoZW1lX2J3KCkKYGBgCgoKTm90ZSwgbG9va2luZyBhIHRoaXMgZ3JhcGgsIHlvdSBjYW4gc2VlIHRoYXQgdGhpcyB2b2ljZWxlc3MgZWZmZWN0IGlzICoqbm90KiogdGhlIGVzdGltYXRlZCBpbnRlcmNlcHQgb2YgcHJlLXZvaWNlbHNzIC9heS8uIEl0IGlzIHRoZSBlc3RpbWF0ZWQgKmRpZmZlcmVuY2UqIGluIGludGVyY2VwdHMgYmV0d2VlbiB0aGVzZSB0d28gbGluZXMuCgojIyMgRXZhbHVhdGluZyB0aGUgbW9kZWwuCgpMZXQncyBsb29rIGF0IHRoZSBtb2RlbCBzdW1tYXJ5IGFnYWluOgoKYGBge3J9CnN1bW1hcnkoYXlfbW9kZWwxKQpgYGAKCklmIHlvdSBvbmx5IGZpdCB0aGlzIG1vZGVsLCBhbmQgZGlkbid0IHBsb3QgYW55IG9mIHRoZSBkYXRhLCB5b3UgbWlnaHQgY29uY2x1ZGU6CgotIFRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgY2hhbmdlIG92ZXIgZGVjYWRlIGZvciAvYXkvLgotIFRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZWZmZWN0IG9mIHZvaWNpbmcgb24gL2F5Ly4KCiMjIEluY2x1ZGluZyBpbnRlcmFjdGlvbnMKCkhvd2V2ZXIsIGxvb2tpbmcgYXQgdGhlIHBsb3QsIGl0J3MgY2xlYXIgc29tZXRoaW5nIG1vcmUgY29tcGxpY2F0ZWQgaXMgZ29pbmcgb24uIApOZWl0aGVyIG9mIHRoZSBsaW5lcyBsb29rIGxpa2UgdGhleSdyZSBwYXNzaW5nIHRocm91Z2ggdGhlaXIgcmVsYXRlZCBkYXRhIHBvaW50cyB2ZXJ5IHdlbGwuClRoZXJlIGlzLCBpbiBmYWN0LCBhbiAqaW50ZXJhY3Rpb24qIGJldHdlZW4gdm9pY2luZyBhbmQgZGF0ZSBvZiBiaXJ0aC4gClByZS12b2ljZWxlc3MgL2F5LyBpcyB1bmRlcmdvaW5nIGEgY2hhbmdlLCB3aGlsZSBlbHNld2hlcmUgL2F5LyBpcyBiYXNpY2FsbHkgc3RheWluZyB0aGUgc2FtZS4KV2UgY2FuIGFjY291bnQgZm9yIHRoaXMgYnkgaW5jbHVkaW5nIHRoaXMgaW50ZXJhY3Rpb24gaW4gdGhlIG1vZGVsOgoKCmBgYHtyfQpheV9tb2RlbDIgPC0gbG0oRjFfbiB+IGRlY2FkZV8xOTAwICogdm9pY2luZywgZGF0YSA9IGF5X21lYW5zKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGF5X21vZGVsMikKYGBgCgpMZXQncyBidWlsZCB1cCB0aGUgZ3JhcGguCgpgYGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIAooSW50ZXJjZXB0KSAgICAgICAgICAgICAgICAgICAxLjMyNjU2NCAgIDAuMDIyMjE5ICA1OS43MDMgIDwgMmUtMTYgKioqCmBgYAoKVGhpcyBpcyB0aGUgZXN0aW1hdGVkIGF2ZXJhZ2UgZm9yIHdoZW4gYWxsIHByZWRpdG9ycyBhcmUgMCAoaS5lLiBkb2IgPSAxOTAwLCB2b2ljaW5nID0gZWxzZSkuCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCAKICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IDE5MDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDIpWzFdICwgCiAgICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJlbHNlIiksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICB0aGVtZV9idygpCmBgYAoKCmBgYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFc3RpbWF0ZSBTdGQuIEVycm9yIHQgdmFsdWUgUHIoPnx0fCkgICAgCmRlY2FkZV8xOTAwICAgICAgICAgICAgICAgICAgLTAuMDIxMjc3ICAgMC4wMDQ0NDMgIC00Ljc4OSAyLjA4ZS0wNiAqKioKYGBgCgpUaGlzIGlzIHRoZSBlc3RpbWF0ZWQgc2xvcGUgKmZvciB0aGUgcmVmZXJlbmNlIGxldmVsKiAoaS5lLiB2b2ljaW5nID0gZWxzZSkKCmBgYHtyIGVjaG8gPSBGfQpiYWRtb2QyIDwtIGxtKEYxX24gfiBkb2IgKiB2b2ljaW5nLCBkYXRhID0gYXlfbWVhbnMpCgpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxOTAwLCAKICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IDE5MDAsIAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZihheV9tb2RlbDIpWzFdICwgCiAgICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJlbHNlIiksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QyKVsxXSwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kMilbMl0sCiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpOb3csIHdlIGdldCBpbnRvIHRoZSBtb3JlIGNvbXBsaWNhdGVkIGNvZWZmaWNpZW50cy4KCgpgYGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIAp2b2ljaW5ndm9pY2VsZXNzICAgICAgICAgICAgIC0wLjE2MTMyOSAgIDAuMDMxNDIzICAtNS4xMzQgMy43NWUtMDcgKioqCmBgYAoKVGhpcyBpcyBob3cgZGlmZmVyZW50IHRoZSBsaW5lIGZvciBwcmUtdm9pY2VsZXNzIC9heS8gaXMgZnJvbSBlbHNld2hlcmUgL2F5LyAqYXQgdGhlIGludGVyY2VwdCogKGkuZS4gd2hlbiBkb2IgPSAxOTAwKS4KCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QyKVsxXSwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kMilbMl0sCiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIGdlb21fc2VnbWVudChhZXMoeSA9IGNvZWYoYXlfbW9kZWwyKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYoYXlfbW9kZWwyKVsxXSArIGNvZWYoYXlfbW9kZWwyKVszXSwKICAgICAgICAgICAgICAgICAgICAgeCA9IDE5MDAsCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAxOTAwLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCksCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpGaW5hbGx5LCB3ZSBoYXZlIHRoZSBpbnRlcmFjdGlvbiBlZmZlY3QuCgpgYGAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIApkZWNhZGVfMTkwMDp2b2ljaW5ndm9pY2VsZXNzIC0wLjEwODQzMyAgIDAuMDA2MjgzIC0xNy4yNTcgIDwgMmUtMTYgKioqCmBgYAoKVGhpcyBpcyB0aGUgbW9zdCBlYXNpbGx5IG1pc2ludGVycHJldGFibGUgcGFyYW1ldGVyIGluIHRoaXMgbW9kZWwuIApJdCBpcyAqbm90KiB0aGUgZXN0aW1hdGVkIHNsb3BlIG9mIHByZS12b2ljZWxlc3MgL2F5Ly4gSXQgaXMgKmhvdyBkaWZmZXJlbnQqIHByZS12b2ljZWxlc3MgL2F5LydzIHNsb3BlIGlzIGZyb20gZWxzZXdoZXJlIC9heS8uIApUaGF0IGlzLCBpZiB5b3UgZHJldyBhIGxpbmUgcGFyYWxsZWwgdG8gZWxzZXdoZXJlIC9heS8sIHRob3MgaXMgaG93IG11Y2ggeW91J2QgaGF2ZSB0byByb3RhdGUgdGhlIHRoZSBsaW5lIHRvIGdldCBwcmUtdm9pY2VsZXNzIC9heS8ncyBzbG9wZS4KCmBgYHtyIGVjaG8gPSBGfQpnZ3Bsb3QoYXlfbWVhbnMsIGFlcyhkb2IsIEYxX24sIGNvbG9yID0gdm9pY2luZykpKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QyKVsxXSwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kMilbMl0sCiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZWxzZSIpLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIGdlb21fc2VnbWVudChhZXMoeSA9IGNvZWYoYXlfbW9kZWwyKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYoYXlfbW9kZWwyKVsxXSArIGNvZWYoYXlfbW9kZWwyKVszXSwKICAgICAgICAgICAgICAgICAgICAgeCA9IDE5MDAsCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAxOTAwLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCksCiAgICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsKICAgIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQgPSBjb2VmKGJhZG1vZDIpWzFdICsgY29lZihheV9tb2RlbDIpWzNdLAogICAgICAgICAgICAgICAgICAgIHNsb3BlID0gY29lZihiYWRtb2QyKVsyXSwKICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMiwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX2FibGluZShhZXMoaW50ZXJjZXB0ID0gY29lZihiYWRtb2QyKVsxXSArIGNvZWYoYmFkbW9kMilbM10sCiAgICAgICAgICAgICAgICAgICAgc2xvcGUgPSBjb2VmKGJhZG1vZDIpWzJdICsgY29lZihiYWRtb2QyKVs0XSwKICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJ2b2ljZWxlc3MiKSwKICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMSwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrICAKICAgIHRoZW1lX2J3KCkKYGBgCgojIyMgQmUgY2FyZWZ1bCB0aGlua2luZyBhYm91dCBtb2RlbHMgd2l0aCBpbnRlcmFjdGlvbnMKClRoaXMgaXMgc3VwZXIgaW1wb3J0YW50IHRvIGtlZXAgaW4gbWluZCwgbGV0J3Mgc2F5IHdlIHJhbiB0aGlzIG1vZGVsLCBhbmQgZ290IHRoZSBmb2xsb3dpbmcgY29lZmZpY2llbnRzOgoKYGBgCihJbnRlcmNlcHQpICAgICAgICAgICAgICAgICAgIDEuMzIgICAgKioqCmRlY2FkZV8xOTAwICAgICAgICAgICAgICAgICAgLTEwICAgICAgKioqCnZvaWNpbmd2b2ljZWxlc3MgICAgICAgICAgICAgLTAuMTYgICAgKioqCmRlY2FkZV8xOTAwOnZvaWNpbmd2b2ljZWxlc3MgIDEwICAgICAgKioqCmBgYAoKVGhlIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGJldHdlZW4gZGF0ZSBvZiBiaXJ0aCBhbmQgdm9pY2luZyBoZXJlIHdvdWxkICoqbm90KiogbWVhbiB0aGF0IHRoZXJlIGlzIHNpZ25pZmljYW50IGNoYW5nZSBmb3IgcHJlLXZvaWNlbGVzcyAvYXkvIG92ZXIgdGltZS4gCkl0IG1lYW5zIHRoZXJlIGlzIGEgKipzaWduaWZpY2FudCBkaWZmZXJlbmNlKiogYmV0d2VlbiB0aGUgc2xvcGUgb2YgZWxzZXdoZXJlIC9heS8gYW5kIHByZS12b2ljZWxlc3MgL2F5Ly4gClRoZSBlc3RpbWF0ZWQgc2xvcGUgb2YgZWxzZXdoZXJlIC9heS8gaW4gdGhpcyBmYWtlIG1vZGVsIGlzIC0xMCwgYW5kIGZvciBwcmUtdm9pY2VsZXNzIC9heS8gaXQncyAtMTAgKyAxMCA9IDAhCgpUaGUgb3RoZXIgdGhpbmcgdG8ga2VlcCBpbiBtaW5kIHdpdGggaW50ZXJwcmV0aW5nIHRoZSByZXN1bHRzIG9mIHRoZSBtb2RlbCBpcyB0aGF0IHRoZSBgdm9pY2luZ3ZvaWNlbGVzc2AgZWZmZWN0IGlzICpub3QqIGFuIGVzdGltYXRlIG9mICJ0aGUgZWZmZWN0IG9mIHZvaWNpbmcuIgpJdCBpcyB0aGUgZXN0aW1hdGVkIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIGxpbmVzICphdCB0aGUgaW50ZXJjZXB0Ki4gCklmIHdlIGNoYW5nZSB3aGVyZSB0aGUgaW50ZXJjZXB0IGlzLCBmb3IgZXhhbXBsZSBieSB1c2luZyBhIGRpZmZlcmVudCBzY2FsaW5nLCB3ZSBhbHNvIGNoYW5nZSB0aGUgdmFsdWUgb2YgdGhpcyBwYXJhbWV0ZXIuIAoKYGBge3J9CnN1bW1hcnkobG0oRjFfbiB+IGRlY2FkZV8xOTAwICogdm9pY2luZywgZGF0YSA9IGF5X21lYW5zKSkKYGBgCgoKYGBge3J9CnN1bW1hcnkobG0oRjFfbiB+IGRlY2FkZV8xOTYwICogdm9pY2luZywgZGF0YSA9IGF5X21lYW5zKSkKYGBgCgpXaXRoIHRoZSBkYXRlIG9mIGJpcnRoIGNlbnRlcmVkIG9uIDE5MDAsIHdlIGdldCBhIHJlbGF0aXZlbHkgd2VhayBlZmZlY3QgKC0wLjE2KS4gCldpdGggdGhlIGRhdGUgb2YgYmlydGggY2VudGVyZWQgb24gMTk2MCwgd2UgZ2V0IGEgbXVjaCBzdHJvbmdlciBlZmZlY3QgKC0wLjgxKS4KVGhhdCdzIGJlY2F1c2UgdGhlcmUgaXMgYSBzdHJvbmcgaW50ZXJhY3Rpb24gYmV0d2VlbiB0aGUgZGF0ZSBvZiBiaXJ0aCBhbmQgdm9pY2luZyBjb250ZXh0LCBhbmQgdGhlcmUgaXMgYSBiaWdnZXIgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZXNlIHR3byBsaW5lcyBpbiAxOTYwIHRoYW4gaW4gMTkwMCEKCgpgYGB7ciBlY2hvID0gRn0KYXlfbW9kZWwzIDwtIGxtKEYxX24gfiBkZWNhZGVfMTk2MCAqIHZvaWNpbmcsIGRhdGEgPSBheV9tZWFucykKZ2dwbG90KGF5X21lYW5zLCBhZXMoZG9iLCBGMV9uLCBjb2xvciA9IHZvaWNpbmcpKSsKICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMpKwogICAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IGNvZWYoYmFkbW9kMilbMV0sCiAgICAgICAgICAgICAgICAgICAgc2xvcGUgPSBjb2VmKGJhZG1vZDIpWzJdLAogICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImVsc2UiKSwKICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHkgPSBjb2VmKGF5X21vZGVsMilbMV0sCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBjb2VmKGF5X21vZGVsMilbMV0gKyBjb2VmKGF5X21vZGVsMilbM10sCiAgICAgICAgICAgICAgICAgICAgIHggPSAxOTAwLAogICAgICAgICAgICAgICAgICAgICB4ZW5kID0gMTkwMCwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAidm9pY2VsZXNzIiksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrCiAgICBnZW9tX3NlZ21lbnQoYWVzKHkgPSBjb2VmKGF5X21vZGVsMylbMV0sCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBjb2VmKGF5X21vZGVsMylbMV0gKyBjb2VmKGF5X21vZGVsMylbM10sCiAgICAgICAgICAgICAgICAgICAgIHggPSAxOTYwLAogICAgICAgICAgICAgICAgICAgICB4ZW5kID0gMTk2MCwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAidm9pY2VsZXNzIiksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRikrICAKICAgIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQgPSBjb2VmKGJhZG1vZDIpWzFdICsgY29lZihiYWRtb2QyKVszXSwKICAgICAgICAgICAgICAgICAgICBzbG9wZSA9IGNvZWYoYmFkbW9kMilbMl0gKyBjb2VmKGJhZG1vZDIpWzRdLAogICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInZvaWNlbGVzcyIpLAogICAgICAgICAgICAgICAgbGluZXR5cGUgPSAxLAogICAgICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGKSsgIAogICAgdGhlbWVfYncoKQpgYGAKCkl0IGlzLCBpbiBmYWN0LCBtb3JlIHRoYW4gcG9zc2libGUgZm9yIGEgcHJlZGljdG9yIGxpa2UgdGhpcyB0byBoYXZlIGFuIGVzdGltYXRlZCB2YWx1ZSBjbG9zZSB0byAwLCBhbmQgYmUgbm9uLXNpZ25pZmljYW50LCBidXQgZm9yIGl0IHRvIGFjdHVhbGx0eSBtYXR0ZXIgYSAqbG90KiB0byB0aGUgbW9kZWwuCgoqKkxlc3NvbnMqKgoKLSBBbHdheXMgdGhpbmsgY2FyZWZ1bGx5IGFib3V0IHRoZSAqbWVhbmluZyogb2YgcHJlZGljdG9ycyBpbiBhIG1vZGVsIHdpdGggaW50ZXJhY3Rpb25zLgotIEFsd2F5cyB0cnkgdG8gZHJhdyB0aGUgZ3JhcGggb3V0LgotIEFsd2F5cyByZW1lbWJlciB0aGUgcGFyYW1ldGVycyBhcmUgZXN0aW1hdGVzIG9mIHRoZSAqZGlmZmVyZW5jZSogZnJvbSB0aGUgcmVmZXJlbmNlIGxldmVscy4KLSBOb24tc2lnbmlmaWNhbnQgIT0gbm90IGltcG9ydGFudC4KCgojIyBDYXRlZ29yaWNhbCBpbnRlcmFjdGlvbnMuCgpXZSdsbCByZXR1cm4gdG8gdGhlIHdlYXRoZXIgZGF0YSB0byBleGFtaW5lIHRoZSBpbnRlcnByZXRhdGlvbiBvZiBjYXRlZ29yaWNhbCBpbnRlcmFjdGlvbnMuIApXZSdsbCBiZSB1c2luZyBzZWFzb24gYW5kIGEgY2F0ZWdvcmljYWwgY29kaW5nIG9mIHllYXIuCgpgYGB7cn0KdGVtcHNfY29tcCA8LSB0ZW1wc19jb21wICU+JQogICAgICAgICAgICAgICAgICBtdXRhdGUoeWVhcl9mYWN0b3IgPSBmYWN0b3IoeWVhcikpCmBgYAoKRml0dGluZyB0aGUgbW9kZWwgaXMgc3RyYWlnaHQgZm9yd2FyZC4KYGBge3J9CnRlbXBzX21vZGVsIDwtIGxtKHRlbXAgfiBzZWFzb24gKiB5ZWFyX2ZhY3RvciwgZGF0YSA9IHRlbXBzX2NvbXApCmBgYAoKYGBge3J9CnN1bW1hcnkodGVtcHNfbW9kZWwpCmBgYAoKVGhlcmUncyBhIGxvdCBnb2luZyBvbiBoZXJlLCBhbmQgaXQgaXMgdmVyeSBlYXN5IHRvIG1pc2ludGVycHJldCB0aGUgcmVzdWx0cyBpZiB5b3UgZG9uJ3QgdHJ5IHRvIGRyYXcgb3V0IHRoZSBncmFwaC4gCldlJ2xsIHRha2UgdGhlIGNvZWZmaWNpZW50cyBpbiBiYXRjaGVzLiBGaXJzdCwgdGhlcmUgaXMgdGhlICJpbnRlcmNlcHQuIgoKYGBgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIAooSW50ZXJjZXB0KSAgICAgICAgICAgICAgICAgICAgMS4yMTUxICAgICAwLjMwOTIgICAzLjkyOSA5LjM3ZS0wNSAqKioKYGBgCgpUaGlzIGlzIHRoZSBlc3RpbWF0ZWQgYXZlcmFnZSB0ZW1wZXJhdHVyZSBmb3IgdGhlIHJlZmVyZW5jZXMgbGV2ZWxzLCB0aGF0IGlzLCBmb3Igc2Vhc29uID0gV2ludGVyLCB5ZWFyID0gMjAxMC4KCgpgYGB7ciBlY2hvPSBGfQp0ZW1wX2NvbXBfbWVhbnMlPiUKICBmaWx0ZXIoc2Vhc29uID09ICJXaW50ZXIiKSU+JQogIGdncGxvdChhZXMoc2Vhc29uLCB0ZW1wKSkrCiAgICBnZW9tX2JsYW5rKCkrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9IG11dGVkKCJibHVlIikpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLjksCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAwLjksCiAgICAgICAgICAgICAgICAgICAgIHkgPSAwLAogICAgICAgICAgICAgICAgICAgICB5ZW5kID0gY29lZih0ZW1wc19tb2RlbClbMV0pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrCiAgICB4bGltKCJXaW50ZXIiLCAiU3ByaW5nIiwgIlN1bW1lciIsICJBdXR1bW4iKSsKICAgIHlsaW0odGVtcF9yYW5nZVsxXSwgdGVtcF9yYW5nZVsyXSkrCiAgICB0aGVtZV9idygpCmBgYAoKTmV4dCwgdGhlcmUgYXJlIHRoZSBzZWFzb24gZWZmZWN0cy4KYGBgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIApzZWFzb25TcHJpbmcgICAgICAgICAgICAgICAgICAgNi4xNjYxICAgICAwLjQ2MDMgIDEzLjM5NSAgPCAyZS0xNiAqKioKc2Vhc29uU3VtbWVyICAgICAgICAgICAgICAgICAgMTIuNzQ3MiAgICAgMC40Mzg1ICAyOS4wNjcgIDwgMmUtMTYgKioqCnNlYXNvbkF1dHVtbiAgICAgICAgICAgICAgICAgICA3LjMxNTAgICAgIDAuNDQ1MSAgMTYuNDM2ICA8IDJlLTE2ICoqKgpgYGAKClJlY2FsbCwgdGhlc2UgYXJlIHRoZSBlc3RpbWF0ZWQgKmRpZmZlcmVuY2VzKiBiZXR3ZWVuIFdpbnRlciBhbmQgdGhlIG5hbWVkIHNlYXNvbi4gQnV0IGJlY2F1c2UgdGhlcmUgaXMgYW4gaW50ZXJhY3Rpb24gZWZmZWN0IGJldHdlZW4gc2Vhc29uIGFuZCB5ZWFyLCB0aGVzZSB2YWx1ZXMgYXJlIGV2ZW4gbW9yZSBzcGVjaWZpYzogdGhlc2UgYXJlIHRoZSBlc3RpbWF0ZWQgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIG9mIHRoZXNlIG5hbWVkIHNlYXNvbnMgYW5kIFdpbnRlciAqKmluIDIwMTAqKiwgYmVjYXVzZSAyMDEwIGlzIHRoZSByZWZlcmVuY2UgbGV2ZWwgZm9yIHllYXIuCgoKCmBgYHtyIGVjaG89IEZ9CgpzcHJpbmcgPC0gZGF0YS5mcmFtZShzZWFzb24gPSBjKDAuOSwgMS45KSwKICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IGMoY29lZih0ZW1wc19tb2RlbClbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzJdKSkKc3VtbWVyIDwtIGRhdGEuZnJhbWUoc2Vhc29uID0gYygwLjksIDIuOSksCiAgICAgICAgICAgICAgICAgICAgIHRlbXAgPSBjKGNvZWYodGVtcHNfbW9kZWwpWzFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVszXSkpCmZhbGwgPC0gZGF0YS5mcmFtZShzZWFzb24gPSBjKDAuOSwgMy45KSwKICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IGMoY29lZih0ZW1wc19tb2RlbClbMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdKSkKCnRlbXBfY29tcF9tZWFucyU+JQogIGZpbHRlcihzZWFzb24gPT0gIldpbnRlciIpJT4lCiAgZ2dwbG90KGFlcyhzZWFzb24sIHRlbXApKSsKICAgIGdlb21fYmxhbmsoKSsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gbXV0ZWQoImJsdWUiKSkrICAKICAgIGdlb21fc2VnbWVudChhZXMoeCA9IDAuOSwKICAgICAgICAgICAgICAgICAgICAgeGVuZCA9IDAuOSwKICAgICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSksCiAgICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsKICBnZW9tX2xhYmVsKGFlcyh4ID0gMC45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdKzEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAKICAgIGdlb21fc3RlcChkYXRhID0gc3ByaW5nLCBncm91cCA9IDEpKwogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMS45LAogICAgICAgICAgICAgICAgICAgICB4ZW5kID0gMS45LAogICAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0sCiAgICAgICAgICAgICAgICAgICAgIHllbmQgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzJdKSwKICAgICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCkpKwogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDEuOSwKICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzJdKzEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxLjksCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAxLjksCiAgICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbMl0pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDIuOSwKICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzNdKzEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAyLjksCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAyLjksCiAgICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrICAgIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDMuOSwKICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdKzEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSAzLjksCiAgICAgICAgICAgICAgICAgICAgIHhlbmQgPSAzLjksCiAgICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbNF0pLAogICAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrICAgCiAgICBnZW9tX3N0ZXAoZGF0YSA9IHN1bW1lciwgZ3JvdXAgPSAxKSsgIAogICAgZ2VvbV9zdGVwKGRhdGEgPSBmYWxsLCBncm91cCA9IDEpKyAgCiAgICB4bGltKCJXaW50ZXIiLCAiU3ByaW5nIiwgIlN1bW1lciIsICJBdXR1bW4iKSsKICAgIHlsaW0odGVtcF9yYW5nZVsxXSwgdGVtcF9yYW5nZVsyXSkrCiAgICB0aGVtZV9idygpCmBgYAoKTmV4dCBpcyB0aGUgeWVhciBlZmZlY3QKCmBgYAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVzdGltYXRlIFN0ZC4gRXJyb3IgdCB2YWx1ZSBQcig+fHR8KSAgICAKeWVhcl9mYWN0b3IyMDExICAgICAgICAgICAgICAgIDMuMDI2NCAgICAgMC40MzczICAgNi45MjAgMS4wM2UtMTEgKioqCmBgYAoKQWdhaW4sIGJlY2F1c2UgdGhlcmUgaXMgYW4gaW50ZXJhY3Rpb24gZWZmZWN0IGJldHdlZW4gc2Vhc29uIGFuZCB5ZWFyLCB0aGlzIGlzIGVzdGltYXRlZCBkaWZmZXJlbmNlIGJldHdlZW4gV2ludGVyIDIwMTAgYW5kIFdpbnRlciAyMDExLiBJJ20gZHJhd2luZyB0aGlzIG9uIHRoZSBncmFwaCBmb3Igd2ludGVyIGluIGEgc29saWQgbGluZSwgYW5kIGZvciBhbGwgb2YgdGhlIG90aGVyIHNlYXNvbnMgaW4gYSBkYXNoZWQgbGluZS4gQXMgd2lsbCBiZSBtYWRlIGNsZWFyIGluIGEgbW9tZW50LCB0aGlzIGlzIGlzIGJlY2F1c2UgdGhlIGludGVyYWN0aW9uIGVmZmVjdHMgY2FuIG9ubHkgYmUgaW50ZXJwcmV0ZWQgaW4gcmVsYXRpb24gdG8gdGhlc2UgZGFzaGVkIGxpbmVzLgoKYGBge3IgZWNobz0gRn0Kd2ludGVyX3llYXIgPC0gZGF0YS5mcmFtZShzZWFzb24gPSBjKDAuOSwgMS4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW1wID0gYyhjb2VmKHRlbXBzX21vZGVsKVsxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs1XSkpCnNwcmluZ195ZWFyIDwtIGRhdGEuZnJhbWUoc2Vhc29uID0gYygxLjksIDIuMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IGMoY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVsyXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVsyXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgY29lZih0ZW1wc19tb2RlbClbNV0pKQpzdW1tZXJfeWVhciA8LSBkYXRhLmZyYW1lKHNlYXNvbiA9IGMoMi45LCAzLjEpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXAgPSBjKGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArIGNvZWYodGVtcHNfbW9kZWwpWzVdKSkKYXV0dW1uX3llYXIgPC0gZGF0YS5mcmFtZShzZWFzb24gPSBjKDMuOSwgNC4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW1wID0gYyhjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKyBjb2VmKHRlbXBzX21vZGVsKVs1XSkpCgp0ZW1wX2NvbXBfbWVhbnMlPiUKICBmaWx0ZXIoc2Vhc29uID09ICJXaW50ZXIiKSU+JQogIGdncGxvdChhZXMoc2Vhc29uLCB0ZW1wKSkrCiAgICBnZW9tX2JsYW5rKCkrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9IG11dGVkKCJibHVlIikpKyAgCiAgZ2VvbV9zdGVwKGRhdGEgPSB3aW50ZXJfeWVhcikrCiAgZ2VvbV9zdGVwKGRhdGEgPSBzcHJpbmdfeWVhciwgbGluZXR5cGUgPSAyKSsgIAogIGdlb21fc3RlcChkYXRhID0gc3VtbWVyX3llYXIsIGxpbmV0eXBlID0gMikrICAKICBnZW9tX3N0ZXAoZGF0YSA9IGF1dHVtbl95ZWFyLCBsaW5ldHlwZSA9IDIpKyAgICAKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxLjEsIHhlbmQgPSAxLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbNV0pLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCkpKwogIGdlb21fbGFiZWwoYWVzKHggPSAxLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs1XSArIDEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDExIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAgIAogIGdlb21fbGFiZWwoYWVzKHggPSAwLjksCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0sCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAxLjksCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVsyXSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIjIwMTAiKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAyLjksCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVszXSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIjIwMTAiKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAzLjksCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs0XSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIjIwMTAiKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrICAKICAgIHhsaW0oIldpbnRlciIsICJTcHJpbmciLCAiU3VtbWVyIiwgIkF1dHVtbiIpKwogICAgeWxpbSh0ZW1wX3JhbmdlWzFdLCB0ZW1wX3JhbmdlWzJdKSsKICAgIHRoZW1lX2J3KCkKYGBgCgpGaW5hbGx5LCB0aGVyZSBhcmUgdGhlIGludGVyYXRpb24gdGVybXMhCgoKYGBgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIApzZWFzb25TcHJpbmc6eWVhcl9mYWN0b3IyMDExICAtMS44NzA3ICAgICAwLjYzMzMgIC0yLjk1NCAgMC4wMDMyNCAqKiAKc2Vhc29uU3VtbWVyOnllYXJfZmFjdG9yMjAxMSAgLTQuMDIxNSAgICAgMC42MTc2ICAtNi41MTEgMS40M2UtMTAgKioqCnNlYXNvbkF1dHVtbjp5ZWFyX2ZhY3RvcjIwMTEgIC0wLjcyNzAgICAgIDAuNjIzMSAgLTEuMTY3ICAwLjI0Mzc1ICAgIApgYGAKClRoZSBlZmZlY3Qgb2YgeWVhciBpbiB0aGUgbW9kZWwgd2FzIGFib3V0IDMsIG1lYW5pbmcgV2ludGVyIDIwMTEgd2FzIDMgZGVncmVlcyB3YXJtZXIgdGhhbiBXaW50ZXIgMjAxMC4gSWYgd2UgbG9vayBhdCB0aGUgU3ByaW5nOlllYXIgaW50ZXJhY3Rpb24gaGVyZSwgaXQgaGFzIGEgdmFsdWUgb2YgLTEuOSwgbWVhbmluZyBTcHJpbmcgMjAxMSB3YXMgMy0xLjkgPSBgciAzLTEuOWAgZGVncmVlIHdhcm1lciB0aGFuIFNwcmluZyAyMDEwLgoKVGhhdCBpcywgdGhlc2UgaW50ZXJhY3Rpb24gdGVybXMgYXJlIHRlbGxpbmcgdXMgaG93IGRpZmZlcmVudCB0aGUgeWVhciBlZmZlY3QgZm9yIGVhY2ggc2Vhc29uIGlzIGZyb20gdGhlIHllYXIgZWZmZWN0IGZvciBXaW50ZXIsIG91ciByZWZlcmVuY2UgbGV2ZWwuIEp1c3QgYmVjYXVzZSBTcHJpbmc6MjAxMSBoYXMgYSBzaWduaWZpY2FudCBuZWdhdGl2ZSB2YWx1ZSBkb2Vzbid0IG1lYW4gU3ByaW5nIDIwMTEgd2FzIGNvbGRlciB0aGFuIFNwcmluZyAyMDEwISBJdCBqdXN0IG1lYW5zIHRoYXQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBTcHJpbmcgMjAxMCBhbmQgU3ByaW5nIDIwMTEgd2FzIG5vdCBhcyBiaWcgYXMgdGhhdCBiZXR3ZWVuIFdpbnRlciAyMDEwIGFuZCBXaW50ZXIgMjAxMSEKClRoZSBzaWduaWZpY2FudCBTcHJpbmc6MjAxMSBlZmZlY3QgYWxzbyAqKmRvZXMgbm90IG1lYW4qKiB0aGF0IFNwcmluZyAyMDExIHdhcyBhIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHRlbXBlcmF0dXJlIHRoYW4gU3ByaW5nIDIwMTAhCgpgYGB7ciBlY2hvPSBGfQp0ZW1wX2NvbXBfbWVhbnMlPiUKICBmaWx0ZXIoc2Vhc29uID09ICJXaW50ZXIiKSU+JQogIGdncGxvdChhZXMoc2Vhc29uLCB0ZW1wKSkrCiAgICBnZW9tX2JsYW5rKCkrCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9IG11dGVkKCJibHVlIikpKyAgCiAgZ2VvbV9zdGVwKGRhdGEgPSB3aW50ZXJfeWVhcikrCiAgZ2VvbV9zdGVwKGRhdGEgPSBzcHJpbmdfeWVhciwgbGluZXR5cGUgPSAyKSsgIAogIGdlb21fc3RlcChkYXRhID0gc3VtbWVyX3llYXIsIGxpbmV0eXBlID0gMikrICAKICBnZW9tX3N0ZXAoZGF0YSA9IGF1dHVtbl95ZWFyLCBsaW5ldHlwZSA9IDIpKyAgICAKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAxLjEsIHhlbmQgPSAxLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbNV0pLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KCkpKwogIGdlb21fbGFiZWwoYWVzKHggPSAxLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs1XSArIDEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDExIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAKCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMi4xLCB4ZW5kID0gMi4xLAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbMl0rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbNV0sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbMl0rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbNV0gKyBjb2VmKHRlbXBzX21vZGVsKVs2XSksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAyLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVsyXSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVs1XSArIGNvZWYodGVtcHNfbW9kZWwpWzZdLTEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDExIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAgIAogIAogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMy4xLCB4ZW5kID0gMy4xLAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbNV0sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gIGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZih0ZW1wc19tb2RlbClbNV0gKyBjb2VmKHRlbXBzX21vZGVsKVs3XSksCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3coKSkrICAKICAgIGdlb21fbGFiZWwoYWVzKHggPSAzLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVszXSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVs1XSArIGNvZWYodGVtcHNfbW9kZWwpWzddLTEsCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDExIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgICAKCgogICAgICBnZW9tX3NlZ21lbnQoYWVzKHggPSA0LjEsIHhlbmQgPSA0LjEsCiAgICAgICAgICAgICAgICAgICB5ID0gY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs0XSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVs1XSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSAgY29lZih0ZW1wc19tb2RlbClbMV0gKyBjb2VmKHRlbXBzX21vZGVsKVs0XSsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmKHRlbXBzX21vZGVsKVs1XSArIGNvZWYodGVtcHNfbW9kZWwpWzhdKSwKICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdygpKSsgIAogICAgZ2VvbV9sYWJlbChhZXMoeCA9IDQuMSwKICAgICAgICAgICAgICAgICAgIHkgPSBjb2VmKHRlbXBzX21vZGVsKVsxXSArIGNvZWYodGVtcHNfbW9kZWwpWzRdKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWYodGVtcHNfbW9kZWwpWzVdICsgY29lZih0ZW1wc19tb2RlbClbOF0tMSwKICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIjIwMTEiKSwKICAgICAgICAgICAgICAgc2l6ZSA9IDIuNSkrICAgIAogICAgCiAgCiAgCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMC45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdLAogICAgICAgICAgICAgICAgICAgbGFiZWwgPSAiMjAxMCIpLAogICAgICAgICAgICAgICBzaXplID0gMi41KSsgICAgCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMS45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbMl0sCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMi45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbM10sCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICBnZW9tX2xhYmVsKGFlcyh4ID0gMy45LAogICAgICAgICAgICAgICAgICAgeSA9IGNvZWYodGVtcHNfbW9kZWwpWzFdICsgY29lZih0ZW1wc19tb2RlbClbNF0sCiAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICIyMDEwIiksCiAgICAgICAgICAgICAgIHNpemUgPSAyLjUpKyAgCiAgICB4bGltKCJXaW50ZXIiLCAiU3ByaW5nIiwgIlN1bW1lciIsICJBdXR1bW4iKSsKICAgIHlsaW0odGVtcF9yYW5nZVsxXSwgdGVtcF9yYW5nZVsyXSkrCiAgICB0aGVtZV9idygpCmBgYAoKIyMgTmV4dCBXZWVrCgotIEludHJvZHVjaW5nIE1peGVkIEVmZmVjdHMgTW9kZWxzCg==